ps / pgrep找不到正在运行的脚本,缺少#!/ bin / bash

问题描述 投票:0回答:1

我发现ps或pgrep在没有“#!/ bin / bash”的情况下找不到运行的脚本

这里是一个示例。sh:

while true
do
    echo $(date)                                                                                                                                                         
done

启动脚本(ubuntu 18.04,Linux版本4.15.0-101-通用):

$echo $BASH
/bin/bash
./sample.sh

打开另一个终端,ps仅找到命令grep

$ps -aux |grep sample.sh
16887  0.0  0.0  16184  1008 pts/4    S+   07:12   0:00 grep --color=auto sample

pgrep一无所获

$pgrep sample
$

但是如果我将“#!/ bin / bash”添加到sample.sh,则现在一切正常:

#!/bin/bash      <-----add this line                                                                                                                                                        
while true
do
    echo $(date)
done

我想知道为什么。

linux shell
1个回答
0
投票

让我们从您的第二个案例开始,即您do拥有#!/bin/bash,因为实际上这是更容易处理的第一个案例。

使用#!/bin/bash

[当您执行以#!/path/to/interpreter开头的脚本时,Linux内核将理解此语法,并以与您在命令行开头显式添加/path/to/interpreter相同的方式为您调用指定的解释器。因此,对于以#!/bin/bash开头的脚本,如果您使用ps ux,则将看到命令行/bin/bash ./sample.sh

没有#!/bin/bash

现在转到缺少#!/bin/bash的另一位置。这种情况更加微妙。

既不是已编译的可执行文件,也不是以#!行开头的文件Linux内核完全无法执行]。>这是一个尝试从python脚本运行不带sample.sh行的#!/bin/bash的示例:

>>> import subprocess
>>> p  = subprocess.Popen("./sample.sh")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/subprocess.py", line 394, in __init__
    errread, errwrite)
  File "/usr/lib/python2.7/subprocess.py", line 1047, in _execute_child
    raise child_exception
OSError: [Errno 8] Exec format error

并且为了证明这不仅仅是一个python问题,这是一个完全相同的示例,而是一个C程序的演示。这是C代码:

#include <stdio.h>
#include <unistd.h>

int main() {

  execl("./sample.sh", "sample.sh", NULL);

  /* exec failed if reached */
  perror("exec failed:");
  return 1;  
}

这是输出:

exec failed:: Exec format error

因此,运行脚本时发生的情况是因为您正在从bash shell调用它

,bash通过在尝试“执行”脚本后直接运行命令来提供一定的容错能力失败。

更详细的是:

  • bash分叉一个子shell,

  • 直接在子shell内调用Linux内核以“执行”您的可执行文件,并且如果成功

  • ,将终止该(子shell)进程并将其替换为运行可执行文件的进程] >
  • 但是,执行成功not

    ,这意味着子shell仍在运行
  • 此时,子shell会读取脚本中的命令并直接开始执行它们。

  • 总体效果与#!/bin/bash情况非常相似,但是由于子shell只是通过派生原始bash进程而启动的,因此它具有相同的命令行,即只有bash,没有任何命令行参数。如果您在ps uxf的输出(进程的树状视图)中寻找此子外壳,您将看到它就像

bash
 \_ bash

而在#!/bin/bash情况下,您得到:

bash
 \_ /bin/bash ./sample.sh
© www.soinside.com 2019 - 2024. All rights reserved.