我有这段代码
#!/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 。有什么建议吗?
答案 0 :(得分:2)
您无法在subshell和get it back outside it中分配变量。
在这种情况下,如果您kill $!
,您将会tee
,{A}会将SIGPIPE
发送到子shell并终止整个事件。因此,子shell中通常不需要PID。
我不确定,但问题可能是你nuking the process from orbit with SIGKILL而不是仅用 kill $PID
轻轻地杀死它。在这种情况下,tee
可能
换句话说,只需使用kill $process_id
即可。请注意,杀死进程并不是同步的 - 您只需向其发送信号并继续进行即可。有关详细信息,请参阅Kill bash processes “nicely”。
答案 1 :(得分:2)
你可以通过twiddling文件描述符获得pid,但这很痛苦。例如:
{ PID=$({ (
echo foo;
echo bar;
sh -c 'echo $$ >&5; exec echo baz' ) |
tr a o; } 5>&1 1>&3 ); } 3>&1
将指定“回声”的pid'到PID。用您的vlc
替换该回音,并将tr
替换为您的sed
,您应该有一个解决方案。
要尝试对此处发生的事情提供一些简化的解释,请首先注意我们正在使用流程替换来分配PID
。 $()
语法只是将命令放在括号内,并将该命令的输出分配给变量。重要的是要记住"输出"这意味着"打印到文件描述符1和#34;的任何内容。在sh
命令中,我们将pid打印到文件描述符5,然后执行echo
。通过使用exec,该echo具有与前一个echo写的相同的pid。现在回声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以确保进程替换完成。