MoreRSS

site iconSanguok | 山月修改

※興趣 ①閩語 ②文言 ③漢字 ④東亞各種文獻 ⑤劇畫稗玩/ACGN ⑥平面設計與排印
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

Sanguok | 山月的 RSS 预览

使用net use命令来临时挂载网络目录

2025-05-02 09:34:00

在Windows CMD中,如果无法直接cd到一个网络目录(专门些的名字叫——通用命名约定〈UNC〉路径),可以使用net use命令来临时挂载网络目录。以下是具体步骤12

  1. 使用net use命令挂载网络目录:
net use Z: \\network_path\shared_folder /user:username password
  • 其中:
    • Z: 是你希望分配给网络目录的本地驱动器号。
    • \\network_path\shared_folder是网络目录的路径。
    • /user:username password是访问网络目录所需的用户名和密码。
    • 挂载完毕后,不仅在CMD内,图形界面的“文件资源管理器”下“此电脑”中也可以看到该挂载目录。
  1. 访问挂载的网络目录:
Z: # 直接输入`Z:`便可切换至该挂载盘符
cd shared_folder # 然后用`cd`命令跳转
  1. 完成操作后卸载网络目录:
net use Z: /delete

补充:pushd命令

在Windows CMD中,pushd命令也可以用来临时挂载网络目录并切换到该目录(而且该方式还更常见一些)。具体步骤如下:

  1. 使用pushd命令挂载网络目录3
set unc_path=\\network_path\shared_folder\b\c
pushd %unc_path%
  1. 执行想要的代码;
  1. 完成操作后使用popd命令卸载网络目录:
popd

使用pushd命令时,它会将网络路径\\network_path\shared_folder挂载到一个可用的盘符(例如Z:),并将工作目录更改为Z:\b\c
但是,这种方法有一个致命的缺点:如果用户对\\network_path\shared_folder\b\c有权限,但对\\network_path\shared_folder没有权限,那么所有在此目录下的命令都会报错:Access is denied4

参考资料

  1. rwv. 在 Windows CMD 中挂载网络路径至本地盘符. rwv 的博客. ↩
  2. Windows掛載共享磁碟/網路磁碟(CIFS)指令. 平凡的幸福. ↩
  3. pushd. Microsoft Learn. ↩
  4. rwv. 在 Windows CMD 中挂载网络路径至本地盘符. rwv 的博客. ↩

进入不断重启的Docker容器的命令行之方法

2024-11-05 10:16:45

停止自动重启

如果容器正在使用docker-compose.yml设置重启策略,临时将restart: always改为restart: no,然后执行docker-compose down停止它。

启动容器进入临时shell

手动启动容器并覆盖其默认命令,以便进入容器并设置权限。运行:

docker run -it --rm --entrypoint /bin/sh your_image_name

退出

做完想做的事后,退出容器命令行:

exit

自建Bookwyrm无法查询远端用户?——开启数据库扩展

2024-10-12 12:01:44

在这篇博文中,笔者(山月)想记录自己如何解决BookWyrm部署过程中遇到的数据库问题,特别是在远程用户搜索时遇到的 “function similarity(character varying, unknown) does not exist” 错误。

背景

背景是笔者(山月)从YunoHost搬迁到现有环境,使用Docker Compose来运行BookWyrm,但在搜索用户时总是出现数据库报错,提示找不到相似度函数。经过查找,了解到这是由于PostgreSQL中缺少pg_trgm扩展导致的。

解法

为了解决这个问题,笔者(山月)进入PostgreSQL数据库,并运行以下命令来安装所需的扩展:

CREATE EXTENSION IF NOT EXISTS pg_trgm;

执行上述命令后,数据库中添加了相应的相似度函数,错误终于得到了修复,用户搜索功能也正常运行了。

总结

看来,有时候问题并不是代码本身,而是数据库的配置。

寄语

希望这篇文章能帮助到遇到类似问题的人,如果你也在使用BookWyrm或其他基于PostgreSQL的应用,记得检查是否已安装所有必要的扩展,尤其是像pg_trgm这样的函数库,它能为用户搜索和文本相似度匹配提供很大的帮助。

BookWyrm无法增添书本、作者、阅读进度……?——解决数据库自增序列问题

2024-10-12 11:28:53

selective focus photography of brown wooden book shelf

引言

最近笔者(山月)将BookWyrm应用从YunoHost迁移到了使用Docker Compose的独立服务器环境,然而在新的环境中遇到了严重的问题:数据库中的表无法正常新增内容,例如无法添加图书、作者,或更新阅读状态等。在调试过程中,每次进行数据迁移操作时,都会遇到数据库主键重复的报错。这篇博文记录了笔者解决这一问题的全过程,希望能够帮助遇到相似困境的朋友们。

问题背景

在将BookWyrm从YunoHost迁移到Docker Compose环境后,笔者(山月)发现新增数据的操作频繁失败,无论是添加图书、作者,还是更新阅读状态,都会遇到数据库报错的问题。具体表现为,当执行Django的migrate命令时,报错显示主键重复(例如 django.db.utils.IntegrityError: duplicate key value violates unique constraint)。

笔者最初的解决方案是手动调整有问题的数据库表的主键自增计数器。但由于涉及的表非常多,一个个手动调整非常低效。这个过程也让笔者意识到,数据库迁移中某些自增序列可能没有同步,导致插入新记录时主键重复。

解决方案:自动校准PostgreSQL自增序列

在多次尝试手动解决主键问题无果后,笔者(山月)决定寻找一种更加自动化的方法,来确保所有数据库表的自增序列都能够同步。笔者最终找到了一个有效的方法:编写一个函数自动校准数据库中所有表的自增序列。

这个函数通过遍历数据库中所有具有自增序列的表,查询每个表的最大主键值,并将自增序列设置为该最大值加一。这样,所有表的自增序列都能够与表中现有数据保持一致,避免了重复主键错误。

下面是这个自动校准函数的实现:

-- 避免重复创建函数
DROP FUNCTION IF EXISTS reset_sequences_for_tables();
-- 重新创建函数
CREATE OR REPLACE FUNCTION reset_sequences_for_tables() RETURNS VOID AS $$
DECLARE
    table_name_text TEXT;
    seq_name TEXT;
    max_id INT;
    default_value TEXT;
    pk_column_name TEXT;
BEGIN
    FOR table_name_text IN
        SELECT t.table_name
        FROM information_schema.tables AS t
        WHERE t.table_schema = 'public'
        AND EXISTS (
            SELECT 1
            FROM information_schema.columns AS c
            WHERE c.table_name = t.table_name
            AND c.column_default ILIKE 'nextval%'
        )
    LOOP
        SELECT column_name INTO pk_column_name
        FROM information_schema.columns AS c
        WHERE c.table_name = table_name_text
        AND c.column_default ILIKE 'nextval%';

        SELECT column_default INTO default_value
        FROM information_schema.columns AS c
        WHERE c.table_name = table_name_text
        AND c.column_name = pk_column_name;

        seq_name := substring(default_value from E'\'(\\w+)\'::regclass');

        IF EXISTS (SELECT 1 FROM pg_class WHERE relname = seq_name) THEN
            EXECUTE 'SELECT MAX(' || pk_column_name || ') FROM ' || table_name_text INTO max_id;

            IF max_id IS NULL THEN
                EXECUTE 'SELECT setval(' || quote_literal(seq_name) || ', 1, false)';
            ELSE
                EXECUTE 'SELECT setval(' || COALESCE(quote_literal(seq_name), 'null') || ', ' || max_id || ')';
            END IF;
        ELSE
            RAISE NOTICE 'Sequence not found for table: %', table_name_text;
        END IF;
    END LOOP;
END;
$$ LANGUAGE plpgsql;

创建函数后,执行它来重置所有自增序列的值:

SELECT reset_sequences_for_tables();

这一步将自动校准所有有自增序列的表的主键序列,让它们与表中的最大ID对应,避免重复主键的情况。

执行结果

执行该函数后,所有表的自增序列都得到了自动校准,数据库主键重复的问题也顺利解决了。执行migrate命令不再报错,BookWyrm的功能恢复正常,现在可以正常添加图书、作者和更新阅读状态。

总结

在迁移BookWyrm应用时,数据库中的自增序列可能因为不同的环境和数据迁移方式而失去同步,导致主键重复的问题。这篇博客记录了如何通过编写一个函数,自动校准PostgreSQL数据库中所有表的自增序列,确保数据一致性并解决问题。

如果你也遇到类似的问题,希望这篇文章能够对你有所帮助。

QNAP NAS使用者注意!千万莫对MariaDB做这件事……

2024-05-04 22:47:30

好吧,我标题党了,非常地微信,非常地小红书。主要是刚刚处理完问题,心情难以平抑。

简单来说,如果您是QNAP NAS使用者,在用QNAP官方提供的MariaDB(如,MariaDB 10)时,千万不要将MariaDB的配置文件(.conf)中,default-storage-engine这一行的默认配置改为InnoDB

经常使用QTS的朋友都知道,QTS虽然是基于Linux设计的,但QNAP有对Linux进行魔改,乃至我们常用的一些软件,如Apache、MySQL等,也都做了自己的魔改。网上的很多文档里提供的/data路径、.conf路径等,在QTS下也是讨不着的。想在QTS找到这些路径,有以下两种思路:

  1. /share/CACHEDEV1_DATA/.qpkg/下面对应的程序目录里翻翻看——例如传说中的MySQL配置文件my.cnf,在QTS下是/.../.qpkg/MariaDB10/etc/mariadb.conf
  2. 去传统的/etc/var之类的目录找找——不过在QTS的场合,多半是一些管道软连接,例如/etc/my.cnf实际指向/mnt/HDA_ROOT/.config/my.cnf;而迷惑人的是,该文件可能是别的MySQL实例的配置文件,而不是我们平常容易用到的QTS应用市场释出的MariaDB的配置文件。

言归正传,MariaDB的配置文件(.conf),即/.../.qpkg/MariaDB10/etc/mariadb.conf,其中的default-storage-engine这一行,默认配置为MyISAM。据说,虽然MyISAM可以作为临时解决方案,但考虑到数据库的完整性和性能,长期来看最好能使InnoDB可用。从个人的业务需求出发,当时是想要改为InnoDB了。

顺带一提,为了确认所有可用的存储引擎及其状态,可以使用这则sql命令:

SHOW ENGINES;

例如,我的场合,就收到如此输出:

+--------------------+---------+-------------------------------------------------------------------------------------------------+--------------+------+------------+
| Engine             | Support | Comment                                                                                         | Transactions | XA   | Savepoints |
+--------------------+---------+-------------------------------------------------------------------------------------------------+--------------+------+------------+
(从略)
| MyISAM             | DEFAULT | Non-transactional engine with good performance and small data footprint                         | NO           | NO   | NO         |
(从略)
| InnoDB             | NO      | Supports transactions, row-level locking, foreign keys and encryption for tables                | NULL         | NULL | NULL       |
+--------------------+---------+-------------------------------------------------------------------------------------------------+--------------+------+------------+
8 rows in set (0.000 sec) 

再次言归正传。所以要我就查找 default-storage-engine 这一行,将其更改为:

default-storage-engine = InnoDB

并确保没有任何行包含 skip-innodb。如果有,需要将其注释掉(在行前加 #)或删除。

然后增加InnoDB相关配置(可选),为了优化 InnoDB 的性能。在 [mysqld] 部分添加以下配置:

innodb_buffer_pool_size = 1G  # 根据你服务器的内存大小调整
innodb_log_file_size = 256M
innodb_log_buffer_size = 32M
innodb_flush_log_at_trx_commit = 1
innodb_file_per_table = 1
innodb_thread_concurrency = 8

修改配置文件后,需要重启数据库服务以使更改生效。一般能想到以下命令:

sudo systemctl restart mariadb.service

或者

sudo systemctl restart mysql.service

然而哪条在我的QTS都用不了。QTS图形界面下的AppCenter则不提供重启选项——这应该是为了数据稳定性考虑。于是我访问了QTS的shell界面,在App Management那边手动restart了MariaDB。

注意,一旦你尝试start或者restart一款程序,就不要再发出或startrestartstop的指令了——直到你在图形界面确确实实看到系统消息栏显示该程序“已启动”(如果你的指令是restart,那么你会先在系统消息栏看到“已停止”,过很久才会看到“已启动”,这时候才安全了),然后再去做你想要做的下一步指令。不要好像没有看到什么反应,就想要重复发出指令——在QTS下,这样会把数据搞坏。

按道理,如果数据库服务器重启成功,则需要验证InnoDB是否启用。重新连接到数据库,然后执行:

SHOW ENGINES;

检查 InnoDB 的状态是否为DEFAULTYES

我顺利重启了MariaDB,然而噩梦这才开始——从shell环境尝试访问mysql,账号密码、什么的照常要求输入,但是输进去后就访问不进mysql命令行环境了。QTS的图形界面那边也打不开MariaDB 10——虽然软件状态显示为“已启动”。

我甚至重启了NAS,并再次尝试从shell、图形界面访问,仍然不行。一度以为是QTS restart一款程序会比较暴力,导致因进程被强行中断而数据坏掉。但又觉得官方提供的实践方式应该不至于不靠谱乃尔。出于试看看的心态找到MariaDB的配置文件(.conf),将其中的default-storage-engine这一行,改回默认配置,即MyISAM。然后按前述方法从shell restart MariaDB 10。

一切恢复正常了。

作为结尾,所以,如果您是QNAP NAS使用者,在用QNAP官方提供的MariaDB(如,MariaDB 10)的时候,千万不要将MariaDB的配置文件(.conf)中,default-storage-engine这一行的默认配置改为InnoDB

解决Wikibase手动导入数据后无法新建实体之问题

2024-03-20 21:30:15

Wikibase简介

Wikibase是一组MediaWiki的扩展功能,用于在中央存储库中处理版本化数据。其主要组件包括:

  • Wikibase存储库:这是一个用于存储和管理数据的扩展功能。
  • Wikibase客户端:它可以从Wikibase存储库检索和嵌入结构化数据。

Wikibase的核心功能是提供一个协作空间,供个人和团体以结构化的方式贡献、编辑和管理信息。它可以轻松地被计算机消费,翻译成多种语言,并作为链接开放数据网络的一部分与世界共享。

解题

MediaWiki具备以.xml格式导出内容的功能,结构化的Wikibase内容(属性、项目、词位)自然不例外。

但是,如果直接从[[Special:Import]]页面上传.xml,会被告知无法导入Wikibase内容。因为系统默认阻止这样的批量上传,避免Wikibase属性(P后面的数字)、项目(Q后面的数字)、词位(L后面的数字)的唯一标识符冲突。

通过在MediaWiki服务器根目录的LocalSettings.php中,加入一行这样的代码:

# 启用Wikibase项目的导入
$wgWBRepoSettings['allowEntityImport'] = true;

来取消限制。

但是这样导入之后,再想通过[[Special:NewItem]]新建项目,却会被告知:

不可以建立一个新页面。 它已经存在。

这是因为想要新建的页面的唯一标识符与现存页面已有的唯一标识符冲突了。

——等等,可是我们在新建项目的时候,又没办法强行指定唯一标识符。难道是系统在不知道唯一标识符已经被占用的情况下,还想要指定该唯一标识符?

原因

是的。

在MediaWiki所使用的数据库里,我们能看到这一数据表:

****_wb_id_counters

****是实际设置的表头。每个人设的表头并不一样。在LocalSettings.php中可以找到表头设定。例如笔者是这么设置的:

# MySQL具体设置
$wgDBprefix = "sanguok_";

那么我就会看到这样的数据表名:

sanguok_wb_id_counters

好的。那么在这一数据表中,有以下内容(以笔者情况为例):

id_type id_value
77696B69626173652D6974656D 6

在Wikibase的wb_id_counters表中,id_typeid_value列用来追踪不同类型实体的ID计数。这里的77696B69626173652D6974656D实际上是一个十六进制编码的字符串。当将这个十六进制字符串解码为ASCII文本时,它代表了某种类型的实体标识符。

让我们将77696B69626173652D6974656D这串十六进制代码解码成ASCII文本来看看它表示什么:

hex_string = "77696B69626173652D6974656D"
ascii_string = bytes.fromhex(hex_string).decode('utf-8')
ascii_string

解码后,77696B69626173652D6974656D代表的ASCII文本是wikibase-item。这意味着在wb_id_counters表中,这个条目是用来追踪Wikibase中“项目”(即item,例如Q1Q2等)的最新ID计数的。在我的情况中,id_value6,这表明追踪到的最新项目ID是Q6

然而,在我的实际情况里,经过批量导入后,Wikibase中最新的条目是item:Q10000,这显然与wb_id_counters表中的记录不匹配。

解决

为了解决这个问题,需要根据实际的最新项目ID(在我的情况下是Q10000),手动更新wb_id_counters表中相应wikibase-item类型的id_value——例如在我的情况下,改为10000

之后,再试看看能否透过[[Special:NewItem]]新建条目。

应该能够成功的。