bash - 从另一个命令启动的 ssh-add 捕获输出
问题描述
这是我的问题的完整版本。我包括所有这些细节以防我的预感是错误的,但你可能想跳到下面的 tl;dr。
我正在尝试编写一个运行任意命令并捕获是否有任何输出打印到终端的函数。我不想干扰正在打印的输出。如果这是一个相关的并发症(可能不是),我还想在命令的退出代码上进行分支。
这是我所拥有的:
function run_and_inspect {
# this subshell ensures the stdout of ${@} is printed and captured
if output=$(
set -o pipefail
"${@}" | tee /dev/tty
); then
did_cmd_work="yes"
else
did_cmd_work="no"
fi
if [ -z "$output" ]; then
was_there_output="no"
else
was_there_output="yes"
fi
echo "output?" $was_there_output
}
通常这工作正常:
$ run_and_inspect true
output? no
$ run_and_inspect "echo hello"
hello
output? yes
但是我发现了一个有问题的命令:
git pull | grep -v 'Already up to date.'
如果没有东西可以拉,这个管道通常不会产生任何输出。但是,如果 ssh-add 需要提示输入密码,则会有输出。它只是没有被注意到run_and_inspect
:
function git_pull_quiet {
git pull | grep -v 'Already up to date.'
}
$ run_and_inspect git_pull_quiet
Enter passphrase for key '/home/foo/.ssh/id_ed25519':
output? no
我的终端有输出。我认为问题在于它不是来自git pull
管道的标准输出,这是run_and_inspect
众所周知的。它从哪里来的?我该如何解决?我也尝试过重定向stderr(即git pull 2>&1
),但没有运气。有什么方法可以直接监控 /dev/tty 吗?
tl;博士(我想!)
我认为这个问题归结为:为什么 log.txt 中没有密码提示?
$ git pull 2>&1 | tee log.txt
Enter passphrase for key '/home/foo/.ssh/id_ed25519':
Already up to date.
$ cat log.txt
Already up to date.
解决方案
为什么 log.txt 中没有密码提示?
使用readpass.c read_passphrase()从openssh load_identify_file打印提示。该函数使用_PATH_TTY "/dev/tty"然后s 到它。open(_PATH_TTY
write()
输出直接显示到终端/dev/tty
,而不是标准流。
就像你对 your 所做的那样tee /dev/tty
,这意味着你的函数也将不起作用。更喜欢保留子程序的标准输出并保留缓冲:
if { tmp=$("$@" > >(tee >(cat >&3))); } 3>&1; then
有什么方法可以直接监控 /dev/tty 吗?
编写您自己的终端仿真器并在其中生成您的进程,然后解析该终端仿真器内的所有输入。类似screen
或tmux
可能有用的程序。
解决方法可能是下载proot
并打开某个文件的文件描述符,然后创建一个仅/dev/tty
包含文件符号链接的 chroot 并在该 chroot 内/proc/self/fd/<that file descriptor>
运行该进程。proot
这个想法是该进程将看到/dev/tty
替换文件的chroot,并将写入您的文件描述符而不是终端。
推荐阅读
- javascript - 关闭 Javascript 警报后阻止关闭 Chrome 扩展弹出窗口
- python - 从字典中设置函数重复值
- python - 在 Flask 分页上刷新页面后 URL 搜索参数丢失
- argo-workflows - argo 工作流 retryStrategy 覆盖
- excel - 用于返回具有多个单元格的每一行的部分文本搜索的第一个实例的公式
- java - 如何在Java中读取外部文件
- vue.js - 使用 Vue.js 计算屏幕大小
- reactjs - 如何在反应中将openweather数据从组件渲染到子组件?
- google-sheets - 谷歌表格查询日期/时间范围
- php - 如何在带有 Laravel 8.x 的 Blade 中使用特定参数检查 Route 是否存在?