【问题标题】:Sleep in a while loop gets its own pidSleep in a while loop 有自己的 pid
【发布时间】:2010-12-15 16:29:02
【问题描述】:

我有一个 bash 脚本,它在循环中执行一些并行处理。我不希望并行进程使 CPU 达到峰值,所以我使用了 sleep 命令。这是一个简化版本。

(虽然是真的;睡觉 99999;完成)&

所以我在 bash 提示符下执行上述行并得到如下内容: [1] 12345

其中[1] 是作业号,12345 是 while 循环的进程 ID (pid)。我做了一个kill 12345 并得到:

[1]+ 终止(虽然为真;做 睡觉99999; 完毕 )

看起来整个脚本已终止。但是,我执行ps aux|grep sleep 并发现 sleep 命令仍然很强大,但有自己的 pid!我可以杀死sleep,一切似乎都很好。但是,如果我要先终止睡眠,while 循环会启动一个新的sleep pid。这让我很惊讶,因为睡眠与 while 循环不平行。循环本身是单一的执行路径。

所以我有两个问题:

  1. 为什么 sleep 命令有自己的进程 ID?
  2. 如何轻松终止 while 循环和睡眠?

【问题讨论】:

    标签: linux bash process-control


    【解决方案1】:
    1. Sleep 有自己的PID,因为它是一个正在运行并只是等待的进程。试试which sleep 看看它在哪里。
    2. 您可以使用ps -uf 查看系统上的进程树。从那里您可以确定睡眠的 shell(运行循环的那个)的 PPID(父 PID)是什么。

    【讨论】:

    • 我明白了。我在想sleep 是 bash 中的内置命令,而不是某个进程。现在更有意义了。
    • 如果您使用 bash,type sleeptype -a sleepwhich 更可取。 which 是外部命令;它无法检测别名、函数或内置命令。比较which echotype echo 的输出。
    • @User1:像echo 这样的东西是内置命令,因为这使它们更高效(在某些情况下,像cd,因为它们具有无法通过运行来实现的语义外部命令)。 sleep 的效率并不重要,因此将其设为内置并没有多大意义。
    【解决方案2】:
    1. 因为“睡眠”是一个过程,而不是内置函数或类似函数

    2. 您可以执行以下操作:

      (while true;do sleep 99999;done)&
      whilepid=$!
      kill -- -$whilepid
      

    上面的代码杀死了进程组,因为 PID 被指定为负数(例如 -123 而不是 123)。另外,它使用了变量$!,它存储了最近执行的进程的PID。

    注意: 当您在交互模式下(即使用命令行提示符)在后台执行任何进程时,它会创建一个新的进程组,这就是发生在您身上的事情。这样,“杀死他们”相对容易,因为你只需要杀死整个进程组。但是,当在脚本中执行相同操作时,它不会创建任何新组,因为所有新进程都属于脚本 PID,即使它们是在后台执行的(默认情况下禁用作业控制)。要在脚本中启用作业控制,您只需将以下内容放在脚本的开头:

    #!/bin/bash
    
    set -m
    

    【讨论】:

    • 太棒了!!你拯救了我的一天
    【解决方案3】:

    您是否尝试过kill %1,其中1 是您在后台启动命令后得到的数字?

    我在启动 (while true;do sleep 99999;done)& 后立即执行此操作,并且它正确终止了它。

    【讨论】:

      【解决方案4】:

      "ps --ppid" 选择所有具有指定父pid的进程,例如:

      $ (while true;do sleep 99999;done)&
      [1] 12345
      
      $ ppid=12345 ; kill -9 $ppid $(ps --ppid $ppid -o pid --no-heading)
      

      【讨论】:

        【解决方案5】:

        你可以杀死进程组。

        要查找您的进程运行的进程组:

        ps --no-headers -o "%r" -p 15864
        

        然后使用以下命令杀死进程组:

        kill -- -[PGID]
        

        您可以在一个命令中完成所有操作。让我们试试吧:

        $ (while true;do sleep 99999;done)&
        [1] 16151
        
        $ kill -- -$(ps --no-headers -o "%r" -p 16151)
        [1]+  Terminated              ( while true; do
            sleep 99999;
        done )
        

        【讨论】:

          【解决方案6】:

          要使用$! 终止while 循环和sleep,您还可以在子shell 中使用trap 信号处理程序。

          (trap 'kill ${!}; exit' TERM; while true; do sleep 99999 & wait ${!}; done)&
          kill -TERM ${!}
          

          【讨论】:

          • 重新登录后不能这样做
          猜你喜欢
          • 2022-12-02
          • 2022-12-27
          • 2014-03-17
          • 2022-12-01
          • 2022-12-02
          • 2017-11-13
          • 1970-01-01
          • 1970-01-01
          • 2019-10-17
          相关资源
          最近更新 更多