tmux 的远程控制功能给我留下了深刻的印象:
tmux new-window -t p12346 'echo foo;sleep 10'
这会在名为 p12346 的会话中创建一个新窗口,并且不会在屏幕上打印任何内容。太棒了。但是我怎样才能告诉上面的命令等到睡眠完成后再返回呢?即我希望执行相同的操作,但需要 10 秒来执行:
time tmux new-window -t p12346 'echo foo;sleep 10'
背景
如果这是可行的,那么它可能会成为 GNU Parallel 的一个功能:当前正在运行的作业可以通过其每个窗口进行访问tmux
,因此您可以实时跟踪每个作业的进度。
因此tmux
不会在前台运行:用户需要附加到它。
答案1
多路复用器1.8 引入了wait-for
可以帮助你做你想做的命令:
time tmux new-window -t p12346 'echo foo;sleep 10;tmux wait-for -S p12346-neww-done' \; \
wait-for p12346-neww-done
“通道”名称(p12346-neww-done
在上面的示例中)可以是您喜欢的任何名称(只要在两个地方都相同;如果您预计可能会同时进行多个调用,那么您可能还希望为每个调用使用唯一的值)。重要的是你在命令之后“等待”信号new-window
(作为同一命令的一部分)多路复用器命令,因此转义分号:多路复用器需要处理它,而不是 shell)并发送信号作为窗口命令的最后一步。
如果您需要更加稳健地防止命令序列以丑陋或不方便的方式中止,那么您可以尝试使用 shell 陷阱来发送信号(为了可读性而重新排列了一点(?)):
time \
tmux new-window -t p12346 '
trap "tmux wait-for -S p12346-neww-done" 0
echo foo
sleep 10
' \; wait-for p12346-neww-done
答案2
您可能会发现以下替代方法更合适:
tmux 之外:
mkfifo fifo && tmux new -d '(echo foo;sleep 3) 9> fifo' && time cat fifo
tmux 内部:
mkfifo fifo && tmux new-window '(echo foo;sleep 10) 9> fifo' && cat fifo
与此的一个区别wait-for
是,这种方法就像死人开关一样:即使由于某种原因该wait-for -S
命令永远无法运行,它也会起作用。
另一个区别是,这将等待主进程的所有子进程退出(除非它们显式关闭其他文件描述符,这对于尝试将自己置于后台的程序来说很常见)。
说明:该cat
命令将等待,直到有东西打开 FIFO 的另一端,然后退出全部该文件描述符的实例被关闭,当持有该文件描述符的所有进程退出时,就会发生这种情况。由于文件描述符的属性,该效果会传播到子进程,默认情况下,子进程继承父进程的打开文件描述符。