【问题标题】:Bash: How to show full list of job processes and kill themBash:如何显示作业进程的完整列表并杀死它们
【发布时间】:2014-04-04 21:48:27
【问题描述】:

我发出命令task1 & task2 dir/ && task3 &

  • Task1 永远不会结束,所以我们将它发送到后台。
  • Task2 更改目录
  • Task3 依赖于 task2 的完成。

发布:jobs -l 将显示:

[1]- 39281 Running                 task1 &
[2]+ 39282 Running                 task2 && task3 &

发布:ps 将显示:

39281 ttys002    0:04.17 task1  
39282 ttys002    0:00.00 task2
39283 ttys002    0:03.66 task3

问题:

  1. 有没有办法在作业命令输出中显示 task3?
  2. 为什么 task3 不显示为自己的工作?
  3. 有没有办法同时杀死所有三个任务?
  4. 如果我杀死 task2,为什么 task3 不会死?
  5. 有没有更好的方法来做到这一点?

目标: 发出一行命令来启动工作流程并将其发送到后台。准备就绪后,一次性杀死所有启动的进程。

对于上下文,就我而言,task1 是一个带有 livereload 的 grunt 任务,因此它应该被发送到后台。 Task2 更改目录,以便 task3 可以查看该目录中更改的文件。

【问题讨论】:

  • 使用pstree -ap 看看tasks之间的关系,可能task3不是你的儿子。
  • 我手头没有电脑,但是如果你把括号括起来让它在一个子shell中运行会发生什么?杀死子shell是否允许您杀死孩子?
  • task2 是一项长期运行的任务吗?我试图重现这一点,但不能。 $ ./task1 & ./task2 && ./task3 & 如果您可以提供重现不良行为的简短脚本示例,这可能会很有用。
  • @michael - 我在 OS X 上,所以 pstree 不可用。
  • cd 是一个内置的 shell,不会出现在 ps 的输出中。此外,如果task2 是一个单独的进程,它对其自己的 工作目录所做的任何更改都不会影响task3

标签: macos bash kill jobs


【解决方案1】:

将 bash 与 job control 一起使用,您可以或多或少地同时杀死最近的两个后台任务

kill %% %-

如果您希望作业不显示 cd 部分,则需要更改当前 shell 中的目录,这意味着隔离 cd 表达式:

sleep 10000 & cd .. && { sleep 20000 & }

【讨论】:

    【解决方案2】:

    这将杀死从该 shell 启动的所有子进程,包括您的后台进程:

    pkill -P $(echo $$)
    

    【讨论】:

      【解决方案3】:

      问题:

      有没有办法在作业命令输出中显示 task3?

      在这种情况下不是。

      为什么 task3 不显示为自己的工作?

      因为 task3 不是一个独立的进程,与其他进程分开启动,就像 task1 一样,但它取决于 task2 的返回值(请记住,task2 可以在进程结束之前向 shell 理想地返回一个值)。只有当 task3 向 shell 返回一个值时,shell 的整个“流程”才会结束。这就是为什么 task2 和 task3 都必须有一个作业 ID。

      有没有办法同时杀死所有三个任务?

      我想不明白这个问题,对不起。您可以使用 pid,因此您可以通过 pid 杀死进程。

      1. 如果我杀死 task2,为什么 task3 不会死?

      因为 task2 不是 task3 的父级,而只是一个将在 之后执行的任务,task2 将向 shell 返回一个非错误代码。 这意味着在这种情况下 task2 和 task3 是两个独立的进程,将在相同的调用上下文中运行。您示例中的 task2 dir/ && task3 & 类似于以下内容:

      (task2 dir/
      if [ $? -eq 0 ]; then
        task3
      fi
      )&
      

      如您所见,task2 和 task3 没有任何联系,而是 task2 的错误代码。

      有没有更好的方法来做到这一点?

      我认为你做得很好。

      换句话说:

      • 从 bash 的角度来看,“作业”是从第一个进程开始到最后一个进程向 shell 返回错误代码时结束的整个进程流。在这种情况下,task2 和 task3 必须有一个作业 ID。这就是为什么我们使用“工作”一词而不是“过程”。

      • 从“进程层次结构”的角度来看,task2 和 task3 是完全独立的,因此它们将具有两个不同的 pid,并且 PPID 将始终是 bash shell。

      关于你的目标:我还是觉得我不明白。你有 task1 和 task3 pid,你可以用一个 kill 命令杀死这两个,比如:kill pid-for-task1 pid-for-task2

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-02-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-02-14
        相关资源
        最近更新 更多