标签: subshell

zsh:命令替换不从其父级继承 stdin

考虑以下命令:

seq 5 | grep $(tail -n1) <(seq 9)
Run Code Online (Sandbox Code Playgroud)

zsh1 中运行时:

tail: error reading 'standard input': Input/output error
Run Code Online (Sandbox Code Playgroud)

现在在 中运行相同的bash,它输出:

5
Run Code Online (Sandbox Code Playgroud)

好的。如评论中所述,命令替换$(tail -n1)继承stdin自其父级。但为什么不发生这种情况zsh呢?
这是zsh唯一的事情还是其他 shell 也会做的事情?它在哪里记录?


现在,如果我通过zsh -c以下方式运行相同的命令:

zsh -c 'seq 5 | grep $(tail -n1) <(seq 9)'
Run Code Online (Sandbox Code Playgroud)

而不是打印相同的错误消息,它会在之后停止tail -n1并等待用户输入,所以如果我输入

19
2
4
Run Code Online (Sandbox Code Playgroud)

然后点击Ctrl+ D,它打印

4
Run Code Online (Sandbox Code Playgroud)

这里发生了什么 ?


1:这是与zsh 5.3.1on archlinux,如果重要的话。

zsh pipe command-substitution stdin subshell

4
推荐指数
1
解决办法
786
查看次数

访问在命令替换中设置的变量

我写了一个简单的脚本

 #!/bin/bash -x
 selentry=`ls -l / | sort ; ts=${PIPESTATUS[0]}`
 echo $ts
Run Code Online (Sandbox Code Playgroud)

但 $ts 什么也没显示。如何显示 $ts 变量,或者如何从变量中的命令获取退出状态代码?

selentry=`ls -l / | sort`
Run Code Online (Sandbox Code Playgroud)

bash shell-script command-substitution subshell variable

4
推荐指数
1
解决办法
1805
查看次数

默默杀死子shell?

我想实现类似这个Q/A 的东西,但是对于一个子外壳。这是我正在尝试的最小示例:

(subshell=$BASHPID
  (kill $subshell & wait $subshell 2>/dev/null) &
sleep 600)

echo subshell done
Run Code Online (Sandbox Code Playgroud)

我怎样才能让它只subshell done返回而不是:

./test.sh: line 4:  5439 Terminated              ( subshell=$BASHPID; ( kill $subshell && wait $subshell 2> /dev/null ) & sleep 600 )
subshell done
Run Code Online (Sandbox Code Playgroud)

编辑:我在这里的术语可能是错误的,通过子外壳我的意思是第一组括号内的过程。

更新:

我想发布来自实际程序的片段以供上下文,上面是一个简化:

# If subshell below if killed or returns error connected variable won't be set
(if [ -n "$2" ];then

      # code to setup wpa configurations here

      # If wifi key is wrong kill subshell …
Run Code Online (Sandbox Code Playgroud)

kill subshell output

4
推荐指数
1
解决办法
2746
查看次数

为什么是 $! 为在后台运行的子 shell 返回错误的进程 ID?

$(sleep 5) &
echo $!
sleep 1
echo "done"
Run Code Online (Sandbox Code Playgroud)

以上输出:

$ ./test.sh
7483
done
Run Code Online (Sandbox Code Playgroud)

但是,如果我在中搜索sleepps aux我会看到:

 ps aux | rg sleep
chris     7484  0.0  0.0 132788  1432 pts/6    S+   12:10   0:00 sleep 1
chris     7485  0.0  0.0 132788  1432 pts/6    S+   12:10   0:00 sleep 5
chris     7519  0.0  0.0  10376  5744 pts/7    S+   12:10   0:00 rg --no-ignore-vcs sleep
Run Code Online (Sandbox Code Playgroud)

sleep 5 进程7485不是7483脚本的输出。这种行为的原因是什么?

shell process subshell

4
推荐指数
1
解决办法
289
查看次数

从 1 行 bash 调用中获取 PID 和返回代码

想象一下我们有一个很长的命令sleep 10(例如)。我们想在另一台服务器上使用 python(paramiko特定的 ssh 库)执行它。

我需要一个 1 行命令来启动命令,打印命令的 PID,然后等待它完成并最终返回命令的退出状态。

到目前为止我尝试过的:

bash -c "echo $BASHPID ; exec sleep 10" ; echo $?
Run Code Online (Sandbox Code Playgroud)

这将打印 shell 的 PID,然后在长命令上调用 exec,然后等待并打印退出状态。问题是$BASHPID打印外部 bash shell 的 PID(可能表明调用bash -c cmd实际上并没有产生一个全新的 shell?)。

如果我在三行中调用上述命令,它就可以工作。

bash
echo $BASHPID ; exec sleep 10
echo $?
Run Code Online (Sandbox Code Playgroud)

任何使用 subshel​​l 的尝试也对我不起作用。

echo $(echo $BASHPID ; exec sleep 10) ; echo $?
Run Code Online (Sandbox Code Playgroud)

这是可行的,但是子shell 将其所有输出管道传送到echo,并且echo 一次打印所有输出,这意味着$BASHPID直到睡眠完成后才会打印。PID 必须立即打印。

bash process subshell exit-status

3
推荐指数
1
解决办法
1525
查看次数

Bash:子shell中的转义引号

当我执行以下命令时:

#!/bin/bash
while IFS= read -r -d '' file; do
    files+=$file
done < <(find -type f -name '*.c' -print0)
echo "${files[@]}"
Run Code Online (Sandbox Code Playgroud)

我没有得到与此相同的结果:

#!/bin/bash
find_args="-type f '*.c' -print0"
while IFS= read -r -d '' file; do
    files+=$file
done < <(find $find_args)
echo "${files[@]}"
Run Code Online (Sandbox Code Playgroud)

如何将第二个场景修复为与第一个相同?

我的理解是,因为双引号中有单引号,单引号会被转义,这会产生一个糟糕的扩展,看起来像这样:

find -type f -name ''\''*.c'\'' -print0
Run Code Online (Sandbox Code Playgroud)

bash quoting escape-characters subshell

3
推荐指数
1
解决办法
1868
查看次数

在子shell中继承的变量而不在主shell中导出

我有下面的shell脚本

var="this is a test"

ls -ltr| while read file
do
     echo $var
done
echo $var
Run Code Online (Sandbox Code Playgroud)

我得到以下输出:

this is a test
this is a test
this is a test
Run Code Online (Sandbox Code Playgroud)

我如何在 while 循环中将变量“var”的值设置为“这是一个测试”,因为管道将产生一个新的子外壳,而且我也没有在主外壳中导出我的“var”变量?

据我所知,为了让孩子从父 shell 继承变量值,我们需要导出变量,但在这种情况下,变量值在没有“导出”语句的情况下被继承。

shell pipe subshell

3
推荐指数
1
解决办法
1333
查看次数

如何以最小的、干燥的、漂亮的方式在同一目录中执行多个文件?

我使用 Ubuntu 16.04 并且我有一个本地化文件,一个执行许多文件的文件,这是我将自己的 GitHub 项目下载到我的机器后得到的。

该文件包含一个 Bash 脚本,名为localize.sh. 我通过~/${repo}/localize.sh.

该文件包含许多行,所有行都具有相同的基本模式(见下文),以在子会话中执行所有相关文件。

这是该文件的实际内容:

#!/bin/bash
~/${repo}/apt/security.sh
~/${repo}/apt/lemp.sh
~/${repo}/apt/certbot.sh
~/${repo}/apt/misc.sh

~/${repo}/third-party/pma.sh
~/${repo}/third-party/wp-cli.sh

~/${repo}/conf/nginx.sh
~/${repo}/conf/php.sh
~/${repo}/conf/crontab.sh

~/${repo}/local/tdm.sh
Run Code Online (Sandbox Code Playgroud)

人们可以注意到重复的~/${repo}/模式。

这不是一个大问题,但减少这些冗余字符仍然会很好,因为这个文件应该变得更大。

实现 DRY 的最简单方法是什么(不要重复该代码的自己版本?

在这种情况下,我个人不想使用一条长线。

编辑:原则上,列出的目录中没有也不应该有任何其他文件,除了localize.sh.


此外,可能 namelocalize.sh以及调用文件的操作localization是一种不好的方法;如果你认为它不好,请在旁注中批评我。

executable shell-script wildcards subshell syntax

3
推荐指数
1
解决办法
186
查看次数

在 shell 或子 shell 中执行代码之间出现意外差异

在 shell 或子 shell 中执行代码之间的这种差异是预期的吗?

$ a() { echo ${@: -1} ; }
$ echo "echo ${*: -1}" > b
$ chmod +x b
$ a 1 2 3
3
$ ./b 1 2 3
bash
$ 
Run Code Online (Sandbox Code Playgroud)

Debian Sid
Bash 版本 5.2.15

bash subshell

3
推荐指数
1
解决办法
279
查看次数

比较没有子shell的if语句中的命令输出

根据https://www.gnu.org/software/bash/manual/bashref.html#Command-Grouping

将命令列表放在大括号之间会导致列表在当前 shell 上下文中执行。

但是当我尝试这个时:if [[ { type -t echo; } = "builtin" ]]; then echo 1; else echo 0; fi我收到以下错误:

-bash:预期条件二元运算符

-bash: `type' 附近的语法错误

没关系,我知道它不应该那样使用。现在我知道,如果我使用,if [[ $( type -t echo ) = "builtin" ]]; then echo 1; else echo 0; fi理论上我将实现所需的功能。

我发现有关防止不必要地使用子 shell 的其他问题得到了回答,但没有人解释比较没有子 shell 的命令的输出。我真正想要的是避免在不需要的地方使用子shell,如果可能的话,我真的很喜欢它在当前的shell上下文中运行这个检查——真的感觉这就是它应该如何完成的。PS 如果没有其他方法,我不介意使用变量和操作。

shell bash string test subshell

2
推荐指数
1
解决办法
2699
查看次数