简体   繁体   English

从另一个命令启动的 ssh-add 捕获 output

[英]Capture output from ssh-add launched by another command

Here's the full version of my question.这是我的问题的完整版本。 I'm including all this detail in case my hunch is wrong, but you may want to skip to the tl;dr below.我包括所有这些细节以防我的预感是错误的,但你可能想跳到下面的 tl;dr。

I'm trying to write a function that runs an arbitrary command and also captures whether any output was printed to the terminal.我正在尝试编写一个运行任意命令的 function 并捕获是否有任何 output 打印到终端。 I don't want to interfere with the output being printed.我不想干扰正在打印的 output。 In case it's a relevant complication (probably not), I also want to branch on the exit code of the command.如果这是一个相关的并发症(可能不是),我还想在命令的退出代码上进行分支。

Here's what I have:这是我所拥有的:

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
}

Generally this works fine:通常这工作正常:

$ run_and_inspect true
output? no

$ run_and_inspect "echo hello"
hello
output? yes

But I've found one problem command:但是我发现了一个有问题的命令:

git pull | grep -v 'Already up to date.'

If there is nothing to pull, this pipeline usually produces no output.如果没有什么可拉的,这条管道通常不会产生 output。 But, if ssh-add needs to prompt for a passphrase, there is output.但是,如果 ssh-add 需要提示输入密码,则output。 It just doesn't get noticed by run_and_inspect :它只是没有被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

There was output to my terminal.我的终端output。 I assume the problem is it didn't come from stdout of the git pull pipeline, which is all run_and_inspect knows about.我认为问题在于它不是来自git pull管道的标准输出,这是run_and_inspect知道的。 Where did it come from?它从哪里来的? How do I fix this?我该如何解决? I've tried redirecting stderr too (ie git pull 2>&1 ), but with no luck.我也尝试过重定向 stderr (即git pull 2>&1 ),但没有运气。 Is there some way to monitor /dev/tty directly?有什么方法可以直接监控 /dev/tty 吗?

tl;dr (I think!) tl;博士(我想!)

I think this question boils down to: why isn't the passphrase prompt in log.txt?认为这个问题归结为:为什么 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.

why isn't the passphrase prompt in log.txt?为什么 log.txt 中没有密码提示?

The prompt is printed from openssh load_identify_file with readpass.c read_passphrase() .提示是从openssh load_identify_file打印的readpass.c read_passphrase() The function does open(_PATH_TTY with _PATH_TTY "/dev/tty" and then write() s to it. function 确实open(_PATH_TTY with _PATH_TTY "/dev/tty"然后write() s 到它。

The output is displayed directly to the terminal /dev/tty , not with standard streams. output 直接显示到终端/dev/tty ,而不是标准流。

Just like you do with your tee /dev/tty , which means that your function will also not work.就像您对tee /dev/tty所做的那样,这意味着您的 function 也将不起作用。 Prefer to preserve the stdout-ness of the child program and preserve buffering:更喜欢保留子程序的标准输出并保留缓冲:

if { tmp=$("$@" > >(tee >(cat >&3))); } 3>&1; then

Is there some way to monitor /dev/tty directly?有什么方法可以直接监控 /dev/tty 吗?

Write your own terminal emulator and spawn your process in it, and then parse all input inside that terminal emulator.编写您自己的终端仿真器并在其中生成您的进程,然后解析该终端仿真器内的所有输入。 Programs like screen or tmux may be of use. screentmux的程序可能有用。

The workaround could be to download proot and open a file descriptor to some file, then create a chroot with just /dev/tty file symlinked to /proc/self/fd/<that file descriptor> and run the process with proot inside that chroot.解决方法可能是下载proot并打开某个文件的文件描述符,然后使用符号链接到/proc/self/fd/<that file descriptor>/dev/tty文件创建一个 chroot,并在该proot中使用根目录运行该进程. The idea is that process will see that chroot with /dev/tty file replaced and will write to your file descriptor instead to the terminal.这个想法是该进程将看到替换/dev/tty文件的 chroot 并将写入您的文件描述符而不是终端。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM