![pmount 挂在 BASH 自动完成上](https://linux22.com/image/77721/pmount%20%E6%8C%82%E5%9C%A8%20BASH%20%E8%87%AA%E5%8A%A8%E5%AE%8C%E6%88%90%E4%B8%8A.png)
每当我尝试将自动完成与pmount
终端结合使用时,终端就会冻结,直到我中止,CTRL+C
这会导致自动完成实际执行。自动完成在任何其他方面都工作得很好,有趣的是,卸载pumount
可以直接成功地自动完成通过pmount
独立于我的工作目录安装的任何驱动器。
非常清晰的分步流程列表:
#start pmount
pmount /de<TAB to autocomplete>
#terminal is frozen
<press CTRL+C once to unfreeze>
pmount /dev/s
pmount /dev/sd<TAB to autocomplete>
#frozen again - note the "d"
<press CTRL+C once to unfreeze>
pmount /dev/sdb
请注意,在这种情况下,/dev/sdb
是唯一存在的闪存驱动器,因此自动完成功能有点智能,不会提供例如/dev/sda
,但它仍然冻结。
我已经测试了一个新的,即未配置的安装,zsh
其中自动完成可以很好地工作pmount
,但表现得不那么智能:pmount /dev/s<TAB>
选择不会减少到/dev/sdb
,但还包括“根硬盘驱动器”/dev/sda
和pumount <TAB>
自动完成当前工作目录的条目。
所以我假设它与 BASH 所谓的智能自动完成行为有关,但我无法远程解决该问题,因为我什至不明白该行为是在哪里配置的。
有什么想法可以解决这个问题以及问题从何而来吗?
系统是Debian 8,pmount
版本是0.9.23,BASH
是4.3.30
答案1
自动完成参考文件存储在/etc/bash_completion.d/pmount
我的系统上。
解决方案 1:(重新)移动/重命名文件
正如 Tom Hunt 所建议的,这是最简单的解决方案。挂起停止,但是自动完成是不智能的,即坚持当前目录的文件名。
解决方案 2:修复自动完成文件
参考文件的问题出现在_pmount()
文件第 62 行的函数中(为了可读性添加了换行符 - 不在原始文件中):
devices="$( command ls $(grep -v '^[[:space:]]*#' /etc/pmount.allow )\
$(grep 1 /sys/block/*/removable |\
sed -e 's,/sys/block/,/dev/,;s,/removable:1,*,') 2>/dev/null |\
sort -u | sed -e 's,\(^/dev/\)\(.*\),\1\2 \2,' ; \
#this last line is of interest, as the errors occur here
grep $mdir /proc/mounts | sed -e 's,.*\($mdir/[^ ]*\).*,\1,' )"
错误在于
grep $mdir /proc/mounts
该变量$mdir
之前未定义,因此脚本挂起。
所以我添加了定义mdir
mdir="$(readlink -f /media)"
取自_pumount()
同一脚本的函数(参见第 75 行),例如第 36 行,似乎mdir
代表米edia(或米数)目录ectory,即pmount
.除此之外,出于安全原因,我还添加了函数mdir
的局部变量_pmount()
(第 25 行)。
自动完成现在停止挂起,但如果安装了可移动驱动器的分区,它的行为会很奇怪,因为它会显示安装的驱动器、其安装点以及来自的所有信息/proc/mounts
,例如:
/media/sdc1
rw,nosuid,nodev,noexec,relatime,uid=1000,gid=1000,fmask=0177,dmask=0077,codepage=437,iocharset=iso8859-1,shortname=mixed,quiet,utf8,errors=remount-ro
这是由于发生错误的同一行 62 引起的,现在问题出在这部分:
grep $mdir /proc/mounts | sed -e 's,.*\($mdir/[^ ]*\).*,\1,'
其中sed
命令必须失败(即不能按预期工作,不能作为命令失败),因为单引号会抑制 的求值$mdir
,因此我将它们更改为双引号:
grep $mdir /proc/mounts | sed -e "s,.*\($mdir/[^ ]*\).*,\1,"
pmount
自动补全现在会跳过 中的信息/proc/mounts
,但仍显示已安装的分区,包括/media/sdc1
安装点。
我无法判断哪个是 的标准行为pmount
,但我执行了以下操作来实际抑制已安装的任何分区的列表,同样,初始行 62 现在更改为(添加换行符以提高可读性 - 应在自动完成脚本中删除) :
devices="$( command ls $(grep -v '^[[:space:]]*#' /etc/pmount.allow )\
$(grep 1 /sys/block/*/removable |\
sed -e 's,/sys/block/,/dev/,;s,/removable:1,*,') 2>/dev/null |\
sort -u | sed -e 's,\(^/dev/\)\(.*\),\1\2 \2,' \
#previous block identical to original script
#the following pipe replaces a semicolon from the original script
#and so does anything that follows
| grep -v "$( if [[ $( grep $mdir /proc/mounts ) ]] ;
then grep $mdir /proc/mounts |\
sed -e "s,.*\($mdir/[^ ]*\).*,\1," \
-e "s,$mdir/,," -e 's, ,\|,g' ;
else echo $mdir ; fi \
)"
)"
现在,与原始脚本相反,前两个grep
s 的输出通过管道传输到 a grep
,其中已安装的分区将被过滤,而不是/media
从 中获取的任何安装/proc/mounts
。该if
循环需要区分空分区/media
和已安装分区的情况。
通过这些更改,pmount
将表现如下:
pmount <TAB to autocomplete>
/dev/sdc /dev/sdc1 /dev/sdc2 /dev/sr0 sdc sdc1 sdc sr0
pmount sdc1
#successful mounting of sdc1
pmount <TAB to autocomplete>
/dev/sdc /dev/sdc2 /dev/sr0 sdc sdc2 sr0
即,已安装的分区被抑制,而驱动器的其他分区(以及驱动器本身)仍然显示。
mdir
请注意第一步定义的重要性!
旁注pmount
请注意,此自动完成扫描/sys/block/*/removable
,1
即仅列出设置了可移动位的设备。然而,其他驱动器可以通过输入来安装,例如pmount /dev/sdd1
,它们只是不会显示在自动完成中。 AFAIK 这是预期的行为,我会保持原样。就我而言,这种情况发生在我正在运行分区的外部硬盘驱动器上ext4
。