我使用 GPG 在 shell 脚本中加密文件(在 Linux 中)。要加密的文件创建时间很长,因此脚本在后台执行,我没有看到密码提示何时出现(提示是文本,而不是 GUI)。如果我在超时内没有输入密码,则操作失败。
文件加密也需要很长时间,所以我不能在调用 GPG 之前放置一个通知命令。
所以我希望 GPG 在密码提示之前通知我。例如,使用铃声 (\07) 或自定义命令。如何做到这一点?
答案1
我假设“脚本在后台执行”意味着你关注其他事情。而不是像 这样的“在后台执行” thescript &
。
执行脚本真的在后台会使其无法从终端读取(直到你fg
这样做);所以如果这是你所做的,那么开始在前台执行脚本,如果需要的话,在单独的终端中执行(tmux
这很好)。
使用以下脚本捕获任意命令输出中可能的密码提示:
#!/usr/bin/expect -f
set command [lindex $argv 0]
spawn -noecho {*}"$argv"
interact -o -re "(^|\[^\n\]+)\\m\[Pp\]\[Aa\]\[Ss\]\[Ss\](\[Ww\]\[Oo\]\[Rr\]\[Dd\]|\[Pp\]\[Hh\]\[Rr\]\[Aa\]\[Ss\]\[Ee\]).*" {
set match "$interact_out(0,string)"
send_user "$match"
send_tty "\a"
spawn -noecho notify-send "Possible password prompt from `$command'" "$match"
wait
}
将其另存为(例如)catch-pass-prompt
并使其可执行(chmod +x catch-pass-prompt
)。示例用法:
./catch-pass-prompt sh -c '
sleep 2
echo line with Passphrase to stdout, bell expected
sleep 2
echo dummy line, no bell expected
sleep 2
echo line with PASSWORD to stderr, bell expected >&2
sleep 2
echo line with compass, no bell expected
sleep 2
echo line with PaSSword1 to tty, bell expected >/dev/tty
'
您将会像 一样使用它./catch-pass-prompt gpg …
。
send_tty "\a"
负责向终端打印铃声字符。
spawn -noecho notify-send …
是如何运行自定义命令的示例(此处notify-send …
)。您可能想要省略或更改它(特别是如果您不使用notify-send
)。
笔记:
我不知道
gpg
,我不知道是否password
是passphrase
要寻找的正确模式。请根据您的需要调整代码。我对自己创建的正则表达式并不十分满意。它太糟糕了,因为它
-nocase
似乎对我不起作用;而且\\m
也没有像我预期的那样工作;我不会进一步研究它。脚本的其他部分也可能不是最佳的。我的经验
expect
有限。将脚本视为概念证明。如示例所示,脚本将捕获并分析给定命令打印到其 stdout、stderr 和 tty(由 提供
expect
)的内容。expect
将合并这些内容并打印到其 stdout。这意味着您将无法区分所请求命令的 stdout 和 stderr,例如,您将无法单独重定向它们。示例代码不要求输入密码。我测试过,
ssh
它确实要求输入密码。您的终端仿真器可能会忽略铃声字符;或者它可能以任何方式对其作出反应。您需要配置终端仿真器,这样铃声就不会被忽视。
我的测试平台:Kubuntu 22.04 LTS,
expect
版本 5.45.4。