是否有可能获得第一个命令(不是后台)的 pid? Zsh,不是 bash
Is it possible to get pid of first command (not background)? Zsh, not bash
我在 zsh 中有:
(sleep 100;program1 & another program & another)&
如何获取 'sleep' 进程的 PID(我需要终止它)?
$! - returns pid 不是睡眠进程
jobs -p - 在这里也没用
killall -9 sleep -没用,因为它会杀死所有睡眠进程,不仅如此。
刚找到解决方案之一:
sleep_pid=`pstree -p $!|grep -o "[[:digit:]]*"|tail -1`
一个选项是从命令集内打印 sleep
的 pid。这可以通过将睡眠进程置于后台,使用 $!
获取 pid,然后使用 wait
阻塞直到它退出来完成。
% (sleep 100 &; print sleep_pid:$!; wait $!; print cmd1 && print cmd2) &
[1] 18055
sleep_pid:18056
% kill 18056
cmd1
cmd2
[1] + done ( sleep 100 & print sleep_pid:$!; wait $!; print cmd1 && print cmd2; )
%
如果您需要以编程方式访问 pid,可以将其写入临时文件或命名管道。
即使您使用的 shell 是 Bourne 风格的,因此支持具有这些语义的 exec 内置,您通常不应该尝试避免使用 sh -c(或等效的)来创建用于此目的的新的、单独的 shell 流程,因为:
一旦 shell 成为 myCommand,就没有 shell 等待 运行 后续命令。 sh -c '回声 $$;执行我的命令;在用 myCommand 替换自身后,foo 将无法尝试 运行 foo。除非你正在编写一个脚本,运行s this 作为它的最后一个命令,否则你不能只使用 echo $$;在 shell 中执行 myCommand,您正在 运行 执行其他命令。
您不能为此使用 subshell。 (echo $$; exec myCommand) 在语法上可能比 sh -c 'echo $$; exec myCommand' 更好,但是当你在 ( ) 中 运行 $$ 时,它给出了父 shell 的 PID,而不是subshell 本身。但是 subshell 的 PID 将成为新命令的 PID。一些 shell 提供了它们自己的非便携式机制来查找子 shell 的 PID,您可以将其用于此目的。特别是,在 Bash 4 中,(echo $BASHPID; exec myCommand) 确实有效。
最后,请注意一些 shell 将执行优化,其中他们 运行 一个命令,就好像由 exec 执行(即,他们首先放弃分叉),当知道 shell 不需要之后做任何事情。一些 shell 尝试在最后一个命令成为 运行 时执行此操作,而其他人只会在命令前后没有其他命令时执行此操作,而其他人则不会执行此操作全部。结果是,如果您忘记编写 exec 而只使用 sh -c 'echo $$; myCommand' 那么它有时会在某些具有 shells 的系统上为您提供正确的 PID。我建议不要依赖这种行为,而是在需要时始终包括 exec 。
在我可以 运行 myCommand 之前,我需要在我的 bash 脚本中设置一些环境变量。这些是否会转移到执行命令 运行ning 的环境中? –
用户5359531
2018 年 5 月 11 日在 15:41
看起来我的环境确实会转移到 exec 命令中。但是,当 myCommand 启动其他进程时,这种方法不起作用,而这些进程是您需要使用的;当我发出 kill -INT 以这种方式获得 pid 时,信号不会到达由 myCommand 启动的子进程,而如果我在当前会话中使用 运行 myCommand 和 Ctrl+C,则信号会正确传播。 –
用户5359531
2018 年 5 月 11 日在 16:43
1个
我试过这个,但是myCommand进程的pid好像是echo $$ +1输出的pid。难道我做错了什么? –
鳄鱼
2018 年 8 月 28 日 10:13
我的命令如下所示:sh -c 'echo $$; exec /usr/local/bin/mbdyn -f "input.file" -o "/path/to/outputdir" > "command_output.txt" 2>&1 &' –
鳄鱼
18 年 8 月 28 日 10:51
这很棒,但是当我尝试将回显值放入变量时它对我不起作用,因此我可以稍后实际使用它来终止进程,例如PID=$(sh -c 'echo $$; exec myCommand') 只是挂起,而如果我删除 PID=$(...) 包装器,它会显示 PID 并立即继续!
我在 zsh 中有: (sleep 100;program1 & another program & another)&
如何获取 'sleep' 进程的 PID(我需要终止它)? $! - returns pid 不是睡眠进程 jobs -p - 在这里也没用
killall -9 sleep -没用,因为它会杀死所有睡眠进程,不仅如此。
刚找到解决方案之一:
sleep_pid=`pstree -p $!|grep -o "[[:digit:]]*"|tail -1`
一个选项是从命令集内打印 sleep
的 pid。这可以通过将睡眠进程置于后台,使用 $!
获取 pid,然后使用 wait
阻塞直到它退出来完成。
% (sleep 100 &; print sleep_pid:$!; wait $!; print cmd1 && print cmd2) &
[1] 18055
sleep_pid:18056
% kill 18056
cmd1
cmd2
[1] + done ( sleep 100 & print sleep_pid:$!; wait $!; print cmd1 && print cmd2; )
%
如果您需要以编程方式访问 pid,可以将其写入临时文件或命名管道。
即使您使用的 shell 是 Bourne 风格的,因此支持具有这些语义的 exec 内置,您通常不应该尝试避免使用 sh -c(或等效的)来创建用于此目的的新的、单独的 shell 流程,因为:
一旦 shell 成为 myCommand,就没有 shell 等待 运行 后续命令。 sh -c '回声 $$;执行我的命令;在用 myCommand 替换自身后,foo 将无法尝试 运行 foo。除非你正在编写一个脚本,运行s this 作为它的最后一个命令,否则你不能只使用 echo $$;在 shell 中执行 myCommand,您正在 运行 执行其他命令。 您不能为此使用 subshell。 (echo $$; exec myCommand) 在语法上可能比 sh -c 'echo $$; exec myCommand' 更好,但是当你在 ( ) 中 运行 $$ 时,它给出了父 shell 的 PID,而不是subshell 本身。但是 subshell 的 PID 将成为新命令的 PID。一些 shell 提供了它们自己的非便携式机制来查找子 shell 的 PID,您可以将其用于此目的。特别是,在 Bash 4 中,(echo $BASHPID; exec myCommand) 确实有效。 最后,请注意一些 shell 将执行优化,其中他们 运行 一个命令,就好像由 exec 执行(即,他们首先放弃分叉),当知道 shell 不需要之后做任何事情。一些 shell 尝试在最后一个命令成为 运行 时执行此操作,而其他人只会在命令前后没有其他命令时执行此操作,而其他人则不会执行此操作全部。结果是,如果您忘记编写 exec 而只使用 sh -c 'echo $$; myCommand' 那么它有时会在某些具有 shells 的系统上为您提供正确的 PID。我建议不要依赖这种行为,而是在需要时始终包括 exec 。 在我可以 运行 myCommand 之前,我需要在我的 bash 脚本中设置一些环境变量。这些是否会转移到执行命令 运行ning 的环境中? – 用户5359531 2018 年 5 月 11 日在 15:41 看起来我的环境确实会转移到 exec 命令中。但是,当 myCommand 启动其他进程时,这种方法不起作用,而这些进程是您需要使用的;当我发出 kill -INT 以这种方式获得 pid 时,信号不会到达由 myCommand 启动的子进程,而如果我在当前会话中使用 运行 myCommand 和 Ctrl+C,则信号会正确传播。 – 用户5359531 2018 年 5 月 11 日在 16:43 1个 我试过这个,但是myCommand进程的pid好像是echo $$ +1输出的pid。难道我做错了什么? – 鳄鱼 2018 年 8 月 28 日 10:13 我的命令如下所示:sh -c 'echo $$; exec /usr/local/bin/mbdyn -f "input.file" -o "/path/to/outputdir" > "command_output.txt" 2>&1 &' – 鳄鱼 18 年 8 月 28 日 10:51 这很棒,但是当我尝试将回显值放入变量时它对我不起作用,因此我可以稍后实际使用它来终止进程,例如PID=$(sh -c 'echo $$; exec myCommand') 只是挂起,而如果我删除 PID=$(...) 包装器,它会显示 PID 并立即继续!