简体   繁体   English

在新的后台运行命令 tmux window 并等待进程完成

[英]Run command in new background tmux window and wait for process to finish

I'm trying to use tmux in a script, so that it runs a command that takes some time (let's say 'ping -c 5 8.8.8.8', for example) in a new hidden pane, while blocking the current script itself until the ping ends.我正在尝试在脚本中使用 tmux,以便它在新的隐藏窗格中运行一个需要一些时间的命令(例如,'ping -c 5 8.8.8.8'),同时阻止当前脚本本身直到ping结束。

By "hidden pane", I mean running the command in a new pane that would be sent in background, and is still accessible by switching panes in order to monitor and/or interact with it (not necessarily ping).通过“隐藏窗格”,我的意思是在一个新窗格中运行命令,该窗格将在后台发送,并且仍然可以通过切换窗格访问以监视和/或与之交互(不一定是 ping)。
(cf. EDIT) (参见编辑)

Here is some pseudo bash code to show more clearly what I'm trying to do:这是一些伪 bash 代码,可以更清楚地显示我正在尝试做什么:

echo "Waiting for ping to finish..."
echo "Ctrl-b + p to switch pane and see running process"

tmux new-window -d 'ping -c 5 8.8.8.8' # run command in new "background" window
tmux wait-for                          # display "Done!" only when ping command has finished

echo "Done!"

I know the tmux commands here don't really have any sense like this, but this is just to illustrate.我知道这里的 tmux 命令实际上没有任何意义,但这只是为了说明。

I've looked at different solutions in order to either send a command in background, or wait until a process has finished in an other pane, but I still haven't found a way to do both correctly.我查看了不同的解决方案,以便在后台发送命令,或者等到进程在另一个窗格中完成,但我仍然没有找到正确执行这两种操作的方法。

EDIT编辑

Thanks to Nicholas Marriott for pointing out the -d option exists when creating a new window to avoid switching to it automatically.感谢 Nicholas Marriott 指出在创建新的 window 时存在-d选项以避免自动切换到它。 Now the only issue is to block the main script until the command ends.现在唯一的问题是在命令结束之前阻止主脚本。

I tried the following, hoping it would work, but it doesn't either (the script doesn't resume).我尝试了以下方法,希望它能起作用,但它也不起作用(脚本没有恢复)。

tmux new-window -d 'ping -c 5 8.8.8.8; tmux wait -S ping' &
tmux wait $!

Maybe there is a way by playing with processes (using fg , bg ...), but I still haven't figured it out.也许有一种方法可以玩进程(使用fgbg ...),但我仍然没有弄清楚。

Similar questions:类似问题:
[1] Make tmux block until programs complete [1] 让 tmux 阻塞直到程序完成
[2] Bash - executing blocking scripts in tmux [2] Bash - 在 tmux 中执行阻塞脚本
[3] How do you hide a tmux pane [3] 如何隐藏一个 tmux 面板
[4] how to wait for first command to finish? [4] 如何等待第一个命令完成?

You can use wait-for but you need to give it a channel and signal that channel when your process is done, something like:您可以使用wait-for但您需要为它提供一个通道并在您的过程完成时向该通道发出信号,例如:

tmux neww -d 'ping blah; tmux wait -S ping'
tmux wait ping
echo done

If you think you might run the script several times in parallel, I suggest making a channel name using mktemp or similar (and removing the file when wait-for returns).如果您认为您可能会并行多次运行该脚本,我建议使用mktemp或类似方法创建频道名称(并在wait-for返回时删除该文件)。

wait-for can't automatically wait for stuff like pane or windows exiting, silence in a pane, and so on, but I would like to see that implemented at some point. wait-for不能自动等待窗格或窗口退出、窗格中的静音等内容,但我希望看到在某个时候实现。

The other answers are only working if you're already within a tmux session.仅当您已经在 tmux session 中时,其他答案才有效。 But if you are outside of it you've to use something like this:但如果你不在它之外,你必须使用这样的东西:

tmux new-session -d 'vi /etc/passwd' \; split-window -d 'vi /etc/group' \; attach

If you want to call this within a script you should check whether or not "$TMUX" is set.如果你想在脚本中调用它,你应该检查是否设置了“$TMUX”。 (Or just unset to force a nested tmux window). (或者只是取消设置以强制嵌套 tmux 窗口)。

#!/bin/sh
export com1="vi /etc/passwd"
export com2="vi /etc/group"
if [ -z $TMUX ]
then
    export doNewSession="new-session -d 'exit 0'"
else
    export doNewSession=""
fi
tmux $doNewSession \; split-window -d $com1 \; split-window -d $com2 \; attach;
[ -z $TMUX ] && exit 0

My solution was to make a named pipe and then wait for input using read :我的解决方案是命名为 pipe,然后使用read等待输入:

#!/bin/sh 

rm -f /wait
mkfifo /wait

tmux new-window -d '/bin/sh -c "ping -c 5 8.8.8.8; echo . > /wait"'

read -t 10 WAIT <>/wait

[ -z "$WAIT" ] && 
  echo 'The operation failed to complete within 10 seconds.' ||
  echo 'Operation completed successfully.'

I like this approach because you can set a timeout and, if you wanted, you could extend this further with other tmux controls to kill the ongoing process if it doesn't end the way you want.我喜欢这种方法,因为您可以设置超时,如果需要,您可以使用其他tmux控件进一步扩展它,以终止正在进行的进程(如果它没有按您想要的方式结束)。

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

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