请看这些:
## Does NOT return to the shell, but Ctrl-C can exit
ssh -S none -fNR 13018:localhost:22 example.com | cat
## Returns to the shell (no "-S none")
ssh -fNR 13019:localhost:22 example.com | cat
## Returns to the shell (no "| cat")
ssh -S none -fNR 13020:localhost:22 example.com
为什么第一个命令不返回到 shell?我希望它能像另一个一样返回到 shell(就像-f
请求 ssh 在命令执行之前进入后台。)并且存在于我给出的 3 个示例中,并且在重定向其输出时似乎表现不稳定(此处用 表示| cat
)。这-S none
不是一个相关的选项(特别是这-S none
应该是默认行为,因为我没有设置任何 ControlMaster 选项),但它似乎仍然改变了-f
.这一切都让我困惑。
有什么方法可以捕获最后一个命令的 stdout/stderr 并让该命令返回到 shell,以便能够根据其输出做出反应?
整个故事:
我想运行 SSH 隧道,并在失败时检查它是否与正在使用的端口有关。在这种情况下,我会尝试另一个端口。我无法使用错误级别,因为它不独特,并且在尝试捕获 stderr 时,我运行了对我来说不清楚的 ssh 行为,它们甚至看起来是假的(使用-S none
和不使用它之间不应该有任何区别,因为它是默认值,我检查了我的~/.ssh/config
值是空的,并且/etc/ssh/ssh_config
没有ControlMaster
设置相关选项。)
编辑:
- 看来我无法重现所描述的第二个示例。进程有时会
ssh
终止吗前有时后cat
进程打开管道?
答案1
奇怪的是,我不明白的是为什么你的第二个例子返回到外壳(我无法重现)。
当您运行时ssh -S none -fNR 13018:localhost:22 example.com | cat
,ssh 进程将保留在后台。它仍然使管道的写入端打开。因此,cat
尚未在其标准输入上看到文件结尾,因此它会继续读取。
按Ctrl+C终止cat
进程(这是作业中唯一仍在运行的部分,因为后台的 ssh 进程已移至其自己的进程组,并且前台 ssh 进程一旦分叉就会终止)。如果后台 ssh 进程尝试写入其标准输出(由于-N
),写入将失败并显示 EPIPE(ssh 阻止 SIGPIPE)。如果您终止了后台 ssh 进程,该cat
进程也会退出。