linux – bash中的奇怪行为(可能还有其他shell?)

前端之家收集整理的这篇文章主要介绍了linux – bash中的奇怪行为(可能还有其他shell?)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

当我做:

/bin/bash -c 'cat /proc/$$/cmdline'

我得到的输出是:

cat/proc/25050/cmdline

而我预期的输出是:

/bin/bash -c 'cat /proc/$$/cmdline'

另一方面,当我这样做时:

/bin/bash -c 'echo $$; cat /proc/$$/cmdline'

我得到了预期的输出,即:

28259
/bin/bash-cecho $$; cat /proc/$$/cmdline

似乎$$是猫的pid而不是bash / sh的pid.
为什么是这样?
shell是否进行某种解析和execve()样式替换?如果是这样,它甚至在取代之前如何知道猫的PID?

最佳答案
为了理解这种行为,我们必须弄清楚bash如何在命令行上执行传递给它的命令.关键是如果命令足够简单,就没有fork(或克隆或类似的东西).

$strace -f -e clone,execve /bin/bash -c 'cat /proc/$$/cmdline'
execve("/bin/bash",["/bin/bash","-c","cat /proc/$$/cmdline"],[/* 80 vars */]) = 0
execve("/bin/cat",["cat","/proc/2942/cmdline"],[/* 80 vars */]) = 0
cat/proc/2942/cmdline+++ exited with 0 +++
$

OTOH如果命令更复杂,bash forks:

$strace -f -e clone,execve /bin/bash -c 'echo $$; cat /proc/$$/cmdline'
execve("/bin/bash","echo $$; cat /proc/$$/cmdline"],[/* 80 vars */]) = 0
2933
clone(child_stack=0,flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,child_tidptr=0x7ff64e6779d0) = 2934
Process 2934 attached
[pid  2934] execve("/bin/cat","/proc/2933/cmdline"],[/* 80 vars */]) = 0
/bin/bash-cecho $$; cat /proc/$$/cmdline[pid  2934] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD,si_code=CLD_EXITED,si_pid=2934,si_uid=1000,si_status=0,si_utime=0,si_stime=0} ---
+++ exited with 0 +++
$

It seems like $$is cat’s pid rather than bash/sh’s pid.

实际上两者都是. bash直接驱逐cat,所以一个成为另一个.

要了解no-fork行为究竟需要什么,我们需要查看源代码.这是评论

      /*
       * IF
       *   we were invoked as `bash -c' (startup_state == 2) AND
       *   parse_and_execute has not been called recursively AND
       *   we're not running a trap AND
       *   we have parsed the full command (string == '\0') AND
       *   we're not going to run the exit trap AND
       *   we have a simple command without redirections AND
       *   the command is not being timed AND
       *   the command's return status is not being inverted
       * THEN
       *   tell the execution code that we don't need to fork
       */

Source

原文链接:/linux/441192.html

猜你在找的Linux相关文章