当我第一次打开终端,或者在一段时间没有使用终端后打开一个新终端时,我的主目录中任何类型的制表符补全(例如ls
和Tab)都需要几秒钟的时间。我以前在使用挂载网络驱动器时见过这种行为autofs
,但我在中没有任何行为~/
。我确实使用 systemd 的自动挂载挂载了 NFS 共享,但那些是在中~/badabing/
,所以一切~/
本身都只是一个本地文件。
如果是自动挂载问题,以下是相关/etc/fstab
行(是的,该服务器称为“badabing”,我在几年前的《黑道家族》狂欢期间给它命名):
badabing:/nfs_shares/music /mnt/badabing/music nfs4 noauto,x-systemd.automount,x-systemd.device-timeout=5sec,x-systemd.idle-timeout=1min 0 0
badabing:/nfs_shares/series /mnt/badabing/series nfs4 noauto,x-systemd.automount,x-systemd.device-timeout=5sec,x-systemd.idle-timeout=1min 0 0
badabing:/nfs_shares/movies /mnt/badabing/movies nfs4 noauto,x-systemd.automount,x-systemd.device-timeout=5sec,x-systemd.idle-timeout=1min 0 0
然后,~/badabing
我有:
$ ls -l ~/badabing/
total 0
lrwxrwxrwx 1 terdon terdon 32 Jan 10 2016 movies -> /mnt/badabing/nfs_shares/movies/
lrwxrwxrwx 1 terdon terdon 31 Jan 10 2016 music -> /mnt/badabing/nfs_shares/music/
lrwxrwxrwx 1 terdon terdon 31 Jan 10 2016 series -> /mnt/badabing/nfs_shares/series
我想对此进行更多调查。我可以以某种方式strace
完成制表符吗?是echo
在各种 bash 完成脚本中添加命令来查看挂起的内容的唯一方法吗?其中有很多,所以我真的宁愿避免这种情况。
那么,是什么导致了这个问题,或者至少我该如何进一步调试它?
答案1
我会这样做:
sudo strace -pXXXX -tfo /tmp/strace.log
在哪里XXXX是 bash 的进程 ID。在我的 NFS 安装目录树之一上快速检查文件名完成情况时,它可以正常工作:
-f
跟踪当前跟踪的进程由于 fork(2) 系统调用而创建的子进程。
-t
为跟踪的每一行添加一天中的时间作为前缀。
有些人可能更喜欢-r
:
-r
每次进入系统调用时打印相对时间戳。这记录了连续系统调用开始之间的时间差。
答案2
运行set -x
以获取每个 shell 命令的跟踪,甚至是由完成框架执行的命令。
从另一个 shell运行strace -f -p 1234
以查看系统调用的跟踪。如果您收到错误“不允许操作”,则可能是由于安全限制将系统调用限制ptrace
为跟踪进程的子进程。 要禁用此限制,请sysctl kernel.yama.ptrace_scope=0
以 root 身份运行。看https://askubuntu.com/questions/41629/after-upgrade-gdb-wont-attach-to-process了解更多信息。或者,您仍然可以使用strace -T -f -o strace.bash bash
(-T
添加每个系统调用所花费的时间)启动 shell并从那里进行实验。
1此限制限制了从您的帐户运行恶意应用程序的影响。它仅在与许多其他限制(通常通过 SELinux 或 AppArmor 影响)结合使用时才有效,特别是将受限制的进程限制为一小组文件。即使在受限 ptrace 模式下,仍然允许 ptrace 的典型用例(即调试器调试子进程)。
答案3
也许这有帮助:
PS4='Line ${LINENO}: ' bash -x /usr/share/bash-completion/bash_completion ls