如何在另一个脚本中停止一个脚本

spe*_*ong 5 kill shell-script pkill

我正在使用终端模拟器运行 Ubuntu 16.04。

我有两个脚本:a.shb.sh.? a.sh调用b.sh

a.sh

echo "a is running"
sleep 5s
bash b.sh
sleep 5s
echo "a is still running"
Run Code Online (Sandbox Code Playgroud)

b.sh

echo "b is now running"
sleep 1000s
echo "Bananas"
Run Code Online (Sandbox Code Playgroud)

有没有办法运行a.shb.sh在它完成之前停止(在它打印香蕉之前)并让a.sh运行完成并打印“a仍在运行”?

我试图把pkill -f b.sh里面a.sh,但两者a.shb.sh停止前a.sh完成。

G-M*_*ca' 5

在某一时刻,你似乎已经接近你想要的了。

\n\n

a.sh

\n\n
#!/bin/sh\n\necho "a.sh running"\nsleep 10s\n(sleep 10s; pkill -f b.sh) &\nbash b.sh\nsleep 10s\npkill -f b.sh\necho "a.sh still running"\n
Run Code Online (Sandbox Code Playgroud)\n\n

b.sh\xe2\x80\x83\xe2\x80\x83\xe2\x80\x83\xe2\x80\x83 (与您的版本相同)

\n\n
echo "b is now running"\nsleep 1000s\necho "Bananas"\n
Run Code Online (Sandbox Code Playgroud)\n\n

(sleep 10s; pkill -f b.sh) &\n中的行创建a.sh一个休眠十秒然后杀死 的子 shell b.sh。\xc2\xa0\n然后将该子 shell 置于后台,\n这样就a.sh可以继续运行。\xc2\xa0\na.sh然后运行b.sh​​,它运行sleep\xc2\xa01000s。\xc2 \xa0\n十秒后,子sleep\xc2\xa010sshell 中的 完成,\n并且它(子 shell)运行pkill\xc2\xa0-f\xc2\xa0b.sh,终止b.sh进程。\xe2\x80\x82\na.sh然后恢复运行。\xc2\xa0\n第二个pkill\xc2\xa0-f\xc2\xa0b.sh不执行任何操作,\n因为该b.sh过程已经终止。

\n\n

这是它运行时发生的情况:

\n\n
$ ./a.sh\na.sh running                                               # 立即运行\nb 现在正在运行                                          # 在上述内容之后大约 10 秒\n./a.sh: line 6: 13684 终止 bash b.sh      # 在上述内容之后大约 10 秒\ na.sh 仍在运行                                        # 在上面之后大约 10 秒\n$                                                          # 在上面之后立即
\n\n

这样做的优点是a.sh可以立即恢复运行\nb.sh如果快速完成。\xc2\xa0\n只有b.sh运行超过 10\xc2\xa0 秒时才会pkill启动。\xc2\xa0\n在另一个答案中,a.sh必须闲置\虽然sleep前面的内容pkill占用了时间,\n即使b.sh已经结束了。

\n\n
\n\n

另一位用户发表评论(现已删除)说

\n\n
\n

我明白了

\n\n
./a.sh\na.sh running\nb is now running\nTerminated\n
Run Code Online (Sandbox Code Playgroud)\n\n

不是你报告的内容。任何想法?

\n
\n\n

那是一个漆黑、风雨交加的夜晚。\xe2\x80\x82 突然,一声枪响!

\n\n

\xe2\x80\x83\xe2\x80\x83\xe2\x80\x83\xe2\x80\x83\xe2\x80\x83\xe2\x80\x83\xe2\x80\x83\xe2\x80\x83\ xe2 \x80\x94这是一个漆黑的暴风雨之夜,史努比\n作者:查尔斯·舒尔茨

\n\n

pgrepand的参数pkill是一个正则表达式;\n具体来说,是一个扩展正则表达式1。\xc2\xa0\n尝试同时运行cat2。\xc2\xa0\n然后执行\xe2\x80\x94 ,它将列出两个 PID,\n并且您可以确认它们是和.\xc2\xa0cutpgrep\xe2\x80\xafc.tpscatcut

\n\n

如果你完全按照我说的做了,\n你真的应该得到和我一样的结果。\xc2\xa0\n但是我\xe2\x80\x99m愿意打赌42\xc2\xa0Zorkmids你做了不同的事情。\xc2 \xa0\n您可以:

\n\n
    \n
  1. a.sh#!/bin/bashshe-bang开头(第一行)\而不是#!/bin/sh, 或
  2. \n
  3. a.shbash\xc2\xa0a.sh而不是./a.sh.
  4. \n
\n\n

突然,一声枪响!

\n\n

b.sh是一个正则表达式,匹配b\n后跟任何字符,后跟sh。\xc2\xa0\n它匹配自身 ( ),\n也匹配、、、和 等b.sh内容。\xc2\xa0\n和 \xe2\x80\xa6 \xe2 \x80\xa6(等等) \xe2\x80\xa6 \xe2\x80\xa6 它\xc2\xa0也匹配!b!shb~shb&shb7shbushbash

\n\n

因此pkill\xc2\xa0-f\xc2\xa0b.sh会杀死所有 bash 进程,\n以及b.sh名称中包含的任何其他进程。\xc2\xa0\n当我运行我运行的内容时,我的登录 shell\n(至少部分不受pkill)是 bash,\n但a.sh正在运行在 \n下/bin/sh(但b.sh在 下运行bash)。\xc2\xa0\n该pkill\xc2\xa0-f\xc2\xa0b.sh命令杀死了该bash\xc2\xa0b.sh进程\n因为它同时 bash包含和b.sh。\xc2\xa0\n但/bin/sh正在运行的进程a.sh不受影响。

\n\n

假设您按照我相信的方式运行它\n(两种选择之一),\n所有脚本进程都在运行bash。\xc2\xa0\n因此该pkill\xc2\xa0-f\xc2\xa0b.sh命令杀死了所有脚本进程。

\n\n

更改pkill\xc2\xa0-f\xc2\xa0b.shpkill\xc2\xa0-f\xc2\xa0\'b\\.sh\'\n(转义点,使其匹配点,而不匹配任何字符),\n并且您应该得到正确的结果。
\n________
\n 1 pgrep(1)
\n 2如果您有两个终端(shell 窗口),\ncat\xe2\x80\xaf|\xe2\x80\xafcut\xe2\x80\xaf-f1在其中一个终端中运行(使用来自终端的输入),\np在另一个终端中运行 -命令。\xc2\xa0\如果您只有一个终端,\n运行sleep\xe2\x80\xaf42 | cat\xe2\x80\xaf|\xe2\x80\xafcut\xe2\x80\xaf-f1\xe2\x80\xaf&\n(如果没有sleep,管道将立即崩溃),\n然后p在同一窗口中运行 - 命令。

\n


小智 3

该行:

bash b.sh
Run Code Online (Sandbox Code Playgroud)

将等待b.sh脚本完成,在结束之前无法在脚本中执行任何操作,b.sh因为a.sh没有控制权。

要让b.sh脚本转到后台并将控制权交还给,a.sh请使用类似于以下内容的命令:

bash b.sh &
Run Code Online (Sandbox Code Playgroud)

这会立即返回控制权a.sh,我们可以得到这样的脚本:

#!/bin/bash 

echo "a is running"
sleep 1s
bash b.sh &
sleep 2
pkill -f 'b\.sh'
sleep 1s
echo "a is still running"
Run Code Online (Sandbox Code Playgroud)

虽然脚本b.sh仍然是:

#!/bin/bash
echo "b is now running"
sleep 1000s
echo "Bananas"
Run Code Online (Sandbox Code Playgroud)

执行后你将得到:

$ ./a.sh
a is running
b is now running
./a.sh: line 7:  8424 Terminated              bash b.sh
a is still running
Run Code Online (Sandbox Code Playgroud)

为了避免出现“作业控制消息”,请使用子 shell,更改bash b.sh &为:

(bash b.sh &)
Run Code Online (Sandbox Code Playgroud)

并且,在执行时,您将得到:

$ ./a.sh
a is running
b is now running
a is still running
Run Code Online (Sandbox Code Playgroud)

编辑:

您报告的“终止”响应的问题是您发布的 pkill 命令pkill -f b.sh正在使用参数作为正则表达式。该正则表达式匹配b后跟任何字符,.后跟sh. 这与名称“bash”匹配,该程序也开始运行a.sh,这解释了为什么a.sh被终止。将 pkill 命令更改为:

pkill -f 'b\.sh'
Run Code Online (Sandbox Code Playgroud)

确保匹配的正则表达式是纯字符串“b.sh”。

您可以通过放置以下内容来查看 pkill 将匹配的进程:

ps -f -o pid,cmd,args |grep 'b.sh'
Run Code Online (Sandbox Code Playgroud)

就在 pkill 之前。

修改为,grep 'b\.sh'发现实际上只匹配一个pid。