建立bash提示时杀死后台进程

时间:2018-09-20 19:46:17

标签: bash shell command-prompt background-process kill

我设法使bash提示延迟加载一些组件,从而具有异步渲染的感觉。延迟加载功能作为(render_async &)的后台进程运行。

从下面的截屏中,您可以看到提示实际上是如何立即加载它的一部分以及其他“延迟加载”的。但是,我注意到的是,如果在加载异步部分之前更改目录,则新提示会被错误的上下文覆盖。

enter image description here

我解决此问题的过程如下:

  • 使用jobs命令检查后台进程
  • 我发现Jobs命令在不在当前工作目录后台的进程旁边显示一个wd:*
  • 查找所有内容并杀死所有具有该模式的后台进程,以避免覆盖

我在我的async命令中添加了一个sleep来模拟它,我可以看到后台进程挂起了。

[1]   Running                 render_async &
[2]-  Running                 render_async &  (wd: ~/Projects/My Personal Space/blog-core)
[3]+  Running                 render_async &

我继续写道:

  jobs | grep 'render_async.*wd:' | cut -d "[" -f2 | cut -d "]" -f1 | while read -r line ; do
    kill "%$line"
  done

理论上应该在其他目录中解析后台作业的ID并杀死它们。但是实际上,我一直在寻找kill: %2: no such job以上的示例。

当我在外壳本身中执行相同的kill命令时,它会完美运行。

在此感谢您的帮助。

其他想法

我尝试命名受https://askubuntu.com/questions/153900/how-can-i-start-a-process-with-a-different-name启发的分支过程(通过将CWD附加到函数名称来命名每个异步过程),其中:

  

bash -c "exec -a MyUniqueProcessName <command> &"替换   当前的shell,没有创建任何新进程,这就是为什么我开始   一个新的shell来调用exec。

     

然后您可以使用以下方法终止该进程:

     

pkill -f MyUniqueProcessName您可以在以下位置启动多个进程   相同的名字,然后pkill -f会杀死所有的人。

,但这一直告诉我,我试图传递给<command>的异步函数未找到,我怀疑它与以下事实有关:它是一个自定义函数,并且正在派生一个新的bash流程,但我不是这里的专家。

谢谢

1 个答案:

答案 0 :(得分:1)

管道会创建一个隐式子外壳,因此在运行while的管道到kill循环中,来自父级的作业是不可见的。怎么样,这至少会杀死第一份工作?

job="$(jobs | grep 'render_async.*wd:' | cut -d "[" -f2 | cut -d "]" -f1)"
kill "%$job"

在我的测试中,$(...)发生在当前外壳中,至少在最初时如此,因此作业表可见。示例:

$ cat &
[1] 8296
$ jobs
[1]+  Stopped                 cat
$ echo "$(jobs| cut -d "[" -f2 | cut -d "]" -f1|head -1)"
1

(顺便说一句,您要杀死的工作是否总是具有相同的工作编号?您可以对%2进行硬编码还是其他类似的代码?)

编辑多作业:

joblist="$(jobs| sed -E 's/^[^0-9]*([0-9]+).*$/\1/'|tr '\n' '@')"
    # E.g., 1@2@
IFS='@'     # Split on @
for job in $joblist     # No double-quotes!
do
    kill "%$job"
done

shell提示符下的工作示例:

$ cat&
[1] 8824
$ cat&
[2] 6452

[1]+  Stopped                 cat
$ jobs
[1]-  Stopped                 cat
[2]+  Stopped                 cat
$ joblist="$(jobs| sed -E 's/^[^0-9]*([0-9]+).*$/\1/'|tr '\n' '@')"
$ IFS=@
$ for job in $joblist; do kill "%$job" ; done

[1]-  Stopped                 cat

[2]+  Stopped                 cat
$ jobs
[1]-  Terminated              cat
[2]+  Terminated              cat
$ jobs
$

我选择@作为分隔符,是因为我认为这对shell没有任何特殊意义。

我不知道这在PS1功能环境中是否有作用。

相关问题