【问题标题】:Getting BASH command PID获取 BASH 命令 PID
【发布时间】:2014-01-08 13:50:50
【问题描述】:

我有这段代码

#!/bin/bash
streamURL=http://devimages.apple.com/iphone/samples/bipbop/gear4/prog_index.m3u8

(
    echo "Debugging for stream: $streamURL";
    echo "Starting debugging...";
    vlc -vvv --color $streamURL --file-caching=10000 2>&1 | sed "s/^/ `date`/";

) | tee  debug.txt &
PROCESS_PID=$!

ps -e | grep $PROCESS_PID 
echo " killing process pid: "
echo $PROCESS_PID;
kill -9 $PROCESS_PID
ps -e | grep vlc #still there

我的问题是我无法将“vlc ...”命令 PID 保存到变量中以便以后将其杀死。如果我在它后面移动“PROCESS_PID=$!”,它将是空的。 sed 之后还需要管道。有什么建议吗?

【问题讨论】:

  • @mbratch 在上面的代码中,我得到的 PID 来自“tee”命令
  • 你为什么要这个pid?如果您只是打算在固定时间段后发送信号,则使用timeout 或将vlc 命令放在为您执行超时的包装脚本中可能要简单得多。
  • @WilliamPursell 我不了解timeout,因为我刚开始使用 bash。谢谢你的建议。我试试看

标签: linux bash debugging pipe pid


【解决方案1】:

您可以通过旋转文件描述符来获取 pid,但这很痛苦。例如:

{ PID=$({ ( 
   echo foo; 
   echo bar;
   sh -c 'echo $$ >&5; exec echo baz' ) |
   tr a o; } 5>&1 1>&3 ); } 3>&1

会将“echo baz”的 pid 分配给 PID。用你的vlc替换那个echo,用你的sed替换tr,你应该有一个解决方案。

为了尝试对这里发生的事情提供一个稍微简化的解释,首先请注意我们正在使用进程替换来对PID 进行分配。 $() 语法简单地将命令放在括号内,并将命令的输出分配给变量。重要的是要记住,这里的“输出”是指“打印到文件描述符 1 的任何内容”。在sh 命令中,我们将pid 打印到文件描述符5,然后执行echo。通过使用 exec,该 echo 与前一个 echo 写入的 pid 相同。现在 echo foo、bar 和 baz 都写入到 tr 的管道中。 tr 的输出被重定向到 fd 3(在编辑之前,这是 fd 2。使用哪个文件描述符大多是任意的,但修改 2 是一个坏主意,以防生成任何错误)并且文件描述符 5 被重定向到 fd 1,使其成为分配给 PID 的进程替换的“输出”。然后在进程替换之外,我们分配 fd 3 以在最初需要的位置提供输出。希望这一段比混淆更容易解释:如果混淆,请查看代码以进行澄清!

不幸的是,如果你想在后台运行它会变得更丑:

{ PID=$({ ( 
   echo foo; 
   echo bar;
   sh -c 'echo $$ >&5; exec 5>&-; exec echo baz' >&3 & ) |
   tr a o; } 5>&1 1>&3 ); } 3>&1

这里需要关闭文件描述符5,以确保进程替换完成。

【讨论】:

  • 哇,我头晕眼花。理解它有问题(bash 新手)^^
  • 是的,它相当模糊。我会尝试添加解释,但代码确实不言自明。
【解决方案2】:

您不能在 subshellget it back outside it 中分配变量。

在这种情况下,如果你 kill $! 你会杀死 tee,这将 (AFAIK) 发送 SIGPIPE 到 subshel​​l 并终止整个事情。所以subshel​​l中一般不需要PID。

我不确定,但问题可能在于您是nuking the process from orbit with SIGKILL,而不是仅仅用kill $PID 轻轻地杀死它。在这种情况下,tee 可能发送 SIGPIPE,因为它不会自行清理。

换句话说,只需使用kill $process_id。请注意,杀死一个进程不是同步的——你只是向它发送一个信号并继续。详情请见Kill bash processes “nicely”

【讨论】:

  • 刚试过,但似乎不起作用:我得到了 tee 的 pid,但杀死它也不会杀死 vlc
  • 请使用您用来终止进程的代码更新问题。
  • 我想要做的是让进程使用睡眠运行大约 20 秒,然后杀死它,尤其是 vlc,然后继续解析日志。这将每分钟重复一次,所以我真的必须清理垃圾:)
  • 其实它就像你说的那样工作,但我需要使用 kill 0 PROCESS_PID。谢谢
  • kill -0(带破折号)杀死进程,它只是检查它是否还活着。 kill 0 $PROCESS_PID 将尝试杀死 PID 0 $PROCESS_PID(应该是$PROCESS_ID,如果有的话)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-25
  • 1970-01-01
  • 2022-01-09
相关资源
最近更新 更多