Linux 获取BASH命令PID

Linux 获取BASH命令PID,linux,bash,debugging,pipe,pid,Linux,Bash,Debugging,Pipe,Pid,我有这段代码 #!/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 | s

我有这段代码

#!/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\u PID=$!”移到它的后面,它将是空的。对于sed,还需要在其后面安装管道。有什么建议吗?

您不能在and中指定变量

在这种情况下,如果您
kill$
您将杀死
tee
,它将(AFAIK)向子shell发送
SIGPIPE
,并终止整个过程。因此,在子shell中通常不需要PID

我不确定,但问题可能是你没有用
kill$PID
轻轻地杀死它。在这种情况下,可能是
tee
不发送SIGPIPE,因为它本身不需要清理


换句话说,只需使用
kill$process\u id
。请注意,终止一个进程并不是同步的——您只是向它发送一个信号并继续进行。有关详细信息,请参阅。

不能在和中指定变量

在这种情况下,如果您
kill$
您将杀死
tee
,它将(AFAIK)向子shell发送
SIGPIPE
,并终止整个过程。因此,在子shell中通常不需要PID

我不确定,但问题可能是你没有用
kill$PID
轻轻地杀死它。在这种情况下,可能是
tee
不发送SIGPIPE,因为它本身不需要清理


换句话说,只需使用
kill$process\u id
。请注意,终止一个进程并不是同步的——您只是向它发送一个信号并继续进行。有关详细信息,请参阅。

您可以通过旋转文件描述符获得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
替换回音,用你的
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以确保进程替换完成。

您可以通过旋转文件描述符获得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
,将
tr
替换为
sed
,您应该有一个解决方案

为了尝试对这里发生的事情提供一个稍微简化的解释,首先请注意,我们使用进程替换来对
PID
进行赋值。
$()
语法只是将命令放在括号内,并将命令的输出赋给变量。记住“output”(输出)这一点很重要这里的意思是“打印到文件描述符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以确保流程替换完成。

@mbrach在上面的代码中,我得到的PID来自“tee”“命令为什么要pid?如果您只是计划在一段固定时间后发送信号,那么使用
timeout
或将
vlc
命令放入为您执行超时的包装器脚本中可能会简单得多。@williampersell我不知道
timeout
,因为我刚开始使用bash。谢谢你的建议。我试试看out@mbratch在上面的代码中,我得到的PID来自“tee”命令,为什么需要PID?如果您只是计划在一段固定时间后发送信号,那么使用
timeout
或将
vlc
命令放入为您执行超时的包装器脚本中可能会简单得多。@williampersell我不知道
timeout
,因为我刚开始使用bash。谢谢你的建议。我会试试的只是试了一下,但似乎不行