首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >子subshells和&& in bash vs zsh的不同行为

子subshells和&& in bash vs zsh的不同行为
EN

Unix & Linux用户
提问于 2022-05-08 12:23:36
回答 1查看 940关注 0票数 10

我对在子shell中运行命令的理解是,当前的shell是分叉的,然后子shell对所需的命令执行进一步的forkexec

在bash和zsh中运行以下代码时,我看到了奇怪的行为:$ ( sleep 5 && sleep 6 )

在<>bash中运行时:

代码语言:javascript
复制
$ echo $
6410
$ ( sleep 5 && sleep 6 )

ps给出了以下内容: CMD:睡眠5个PID:6590 PPID:6589

然后: CMD:睡眠6 PID:6616 PPID:6589

这一切对我来说都是有意义的。sleep 5sleep 6都有相同的父级(可能是子subshell)。

但是,在<>zsh中,我得到以下内容:

代码语言:javascript
复制
$ echo $
1987
$ ( sleep 5 && sleep 6 )

ps给出了以下内容: CMD:睡眠5个PID:7576 PPID:7575

然后: CMD:睡眠6 PID:7575 PPID:1987

我无法解释为什么sleep 5将用于运行sleep 6的进程作为其父进程,而用于运行sleep 6的进程以原始shell作为其父进程?

EN

回答 1

Unix & Linux用户

发布于 2022-05-08 13:37:22

你可以在Bash得到类似的东西:

代码语言:javascript
复制
$ echo $
26328
$ ( /bin/sleep 1234 )
代码语言:javascript
复制
$ ps -o pid,ppid,stat,args -C sleep
  PID  PPID STAT COMMAND
26473 26328 S+   /bin/sleep 1234

Bash在那里所做的是,虽然它为子subshell做了分叉,但它认识到只有一个命令要在那里运行,然后只需要执行sleep作为一个优化,从而节省额外的分叉。它对像bash -c '/bin/sleep'这样的东西也是一样的

只是Bash只在一个命令的情况下才这样做,使用( true; /bin/sleep 2345 ),您也会看到中间的shell进程。显然,zsh在优化方面更具侵略性,也跳过了列表的最后一个命令的叉。

无论如何,不需要在另一个进程中运行子there。只是它运行在另一个shell执行环境中,这是来自POSIX壳语言规范的一个短语。现在,该环境确实包括了诸如umask和当前工作目录( OS级别上的每个进程)以及shell变量等内容,因此通过分叉实现单独的环境是一种简单的方法。但这不是要求。

例如,ksh做了一些不同的事情,在这个简单的子subshell中根本没有分叉。但是它仍然有效,我们得到的FOO值是从外壳级别得到的:

代码语言:javascript
复制
$ strace -etrace=clone,fork,vfork -f ksh -c 'FOO=out; ( FOO=in; true ); echo "$FOO"'
out
+++ exited with 0 +++

巴什和兹什会在那里分叉。另外,ksh将sleep实现为内置的,因此除非您显式地使用/bin/sleep,否则您将不会在那里看到它的进程。

票数 13
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/701831

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档