标签: subshell

管道时陷阱是否按预期工作?

以下是问题演示的最小代码:http: //pastebin.com/5TXDpSh5

#!/bin/bash
set -e
set -o pipefail

function echoTraps() {
    echo "= on start:"
    trap -p
    trap -- 'echo func-EXIT' EXIT
    echo "= after set new:"
    trap -p
    # we can ensure after script done - file '/tmp/tmp.txt' was not created
    trap -- 'echo SIG 1>/tmp/tmp.txt' SIGPIPE SIGHUP SIGINT SIGQUIT SIGTERM
}

trap -- 'echo main-EXIT1' EXIT

echo "===== subshell trap"
( echoTraps; )

echo "===== pipe trap"
echoTraps | cat

echo "===== done everything"
Run Code Online (Sandbox Code Playgroud)

产量

===== …
Run Code Online (Sandbox Code Playgroud)

bash pipe subshell bash-trap

7
推荐指数
1
解决办法
775
查看次数

在同一子shell中分配和使用变量

我正在做一些非常简单的事情:v=5 echo "$v"并期望它打印出来5.但事实并非如此.刚刚设置的值不适用于下一个命令.

最近了解到 " 在大多数shell中,管道的每个命令都在一个单独的SubShell中执行 ".但是,在这种情况下,两个命令都在同一个子shell中执行.

为什么会这样?有没有办法让这个工作?

完整示例:

$ v=1
$ v=5 echo "$v"
1                   # I expected 5!
Run Code Online (Sandbox Code Playgroud)

bash scope subshell

7
推荐指数
1
解决办法
664
查看次数

Shell函数是否在子shell中运行

我试图解决一个问题,在我看来,你无法将开放的db2连接传递给子shell.

我的代码组织如下:

驱动程序脚本(中my_driver.sh)

# foo.sh defines baz() bar(), which use a db2 connection
# Also the "$param_file" is set in foo.sh!
source foo.sh

db2 "connect to $dbName USER $dbUser using $dbPass"

function doit
{
    cat $param_file | while read params
    do
        baz $params
        bar $params
    done
}

doit
Run Code Online (Sandbox Code Playgroud)

我简化了我的代码,但上面的内容已经足够了.我从上面开始:

my_driver.sh
Run Code Online (Sandbox Code Playgroud)

现在,我真正的问题是子shell中没有db2连接:

我累了:

. my_driver.sh
Run Code Online (Sandbox Code Playgroud)

没有帮助

如果我从命令行手动执行:

source foo.sh
Run Code Online (Sandbox Code Playgroud)

$params手动设置:

baz $params
bar $params
Run Code Online (Sandbox Code Playgroud)

然后它确实有效!如此看来,doit还是别的什么行为,如果barbaz从子shell执行.

如果我能以某种方式弄清楚如何将db2 open连接传递给subshel​​l,那我会很高兴.

否则,这些shell函数在我看来它们在子shell中运行.有办法吗?

bash subshell

7
推荐指数
1
解决办法
4362
查看次数

执行单个命令时Bash'吞咽'子shell子进程

陷入意外bash/ sh行为,我想知道有人可以解释其背后的基本原理,并为下面的问题提供解决方案.

在交互式bashshell会话中,我执行:

$ bash -c 'sleep 10 && echo'

随着psLinux上,它看起来是这样的:

\_ -bash \_ bash -c sleep 10 && echo \_ sleep 10

进程树是我所期望的:

  • 我的交互式bash shell进程($)
  • 子shell进程(bash -c ...)
  • 睡眠儿童过程

但是,如果我的命令部分bash -c单个命令,例如:

$ bash -c 'sleep 10'

然后吞下中间的子shell,并且我的交互式终端会话在孩子处理时"直接"执行睡眠.进程树看起来像这样:

\_ -bash \_ sleep 10

所以从流程树的角度来看,这两个产生了相同的结果:

  • $ bash -c 'sleep 10'
  • $ sleep 10

这里发生了什么?

现在我的问题是:有没有办法强制中间shell,不管传递给表达式的复杂性如何bash -c ...

(我可以附加类似于; echo;我的实际命令和"工作"的东西,但我宁愿不这样做.是否有更合适的方法来强制中间过程存在?)

(编辑: …

linux bash shell subshell

7
推荐指数
1
解决办法
357
查看次数

bash:如何更新隐式子shell中的关联数组?

问题:我无法在while循环中更新数组.插图(不是实际问题):

declare -A wordcounts
wordcounts["sentinel"]=1000
ls *.txt | while read f; do
  # assume that that loop runs multiple times
  wordcounts[$f]=$(wc -w  $f)
  echo ${wordcounts[$f]}  # this prints actual data
done
echo ${!wordcounts[@]}  # only prints 'sentinel'
Run Code Online (Sandbox Code Playgroud)

这不起作用,因为管道在子shell中运行后循环.循环对变量所做的所有更改wordcounts仅在循环内可见.

export wordcounts没有用.

唉,我似乎需要管道while read部件,所以重写上面的代码的方法for并不是我想要的.

有没有合法的方法来更新循环中的关联数组形式,或者一般的子shell?

arrays bash loops associative-array subshell

6
推荐指数
1
解决办法
1541
查看次数

Bash获取在子shell中启动的进程的进程ID

我在这里看这个问题,但它似乎不适合我:如何在命令行上获取bash子进程的进程ID

所以我有一个命令,我在子shell中开始,如:

(sleep 10 &)
Run Code Online (Sandbox Code Playgroud)

然后,我如何获取该睡眠命令的进程ID,并等待它?

如果我在上面的链接中没有任何进程ID与我看到的匹配后执行ps.

谢谢.

bash shell process subshell

5
推荐指数
1
解决办法
3576
查看次数

bash中的括号 - 子shell与分组

在bash的联机帮助页面中,在" 复合命令 "部分下,有以下两个条目:

(list)列表在子shell环境中执行(参见下面的COMMAND EXECUTION ENVIRONMENT).影响shell环境的变量赋值和内置命令在命令完成后不会保持有效.返回状态是列表的退出状态.

test[[:

(expression)返回表达式的值.这可以用于覆盖运算符的正常优先级.

我能看到的唯一区别是,在一个中,括号旁边没有空格,而另一个则是.这实际上区分了分组与子shell,还是依赖于上下文?

换句话说,如果我跑

if ! [ 2 -eq 2 ] || ( [ 2 -eq 2 ] && [ 4 -eq 4 ] ); then echo "hello"; fi
Run Code Online (Sandbox Code Playgroud)

这只是分组条件还是在子shell中运行?

bash grouping subshell

5
推荐指数
1
解决办法
708
查看次数

在 bash 中用其内容替换“源文件”并扩展变量

在 script.sh 中,

source a.sh
source b.sh

CMD1
CMD2
CMD3
Run Code Online (Sandbox Code Playgroud)

如何source *.sh用它们的内容替换(不执行命令)?我想看看 bash 解释器在获取文件并扩展所有变量后执行什么。

我知道我可以使用set -n -v或运行bash -n -v script.sh 2>output.sh,但这不会替换源命令(如果 a.sh 或 b.sh 包含变量,则更少)。

我想过使用子shell,但这仍然没有扩展源代码行。我在源代码行之前和之后尝试了set +n +v和的组合set -n -v,但这仍然不起作用。

我将使用 ssh 将该输出发送到远程机器。我可以使用<<output.sh管道将内容传输到 ssh 命令中,但我无法以 root 身份登录到远程计算机,但我是 sudoer。因此,我想我可以创建脚本并将其作为 base64 编码的字符串发送(使用那个聪明的技巧base64 script | ssh remotehost 'base64 -d | sudo bash'

有解决办法吗?或者你有更好的主意吗?

bash set expansion subshell

5
推荐指数
1
解决办法
905
查看次数

bash - pipe创建一个子shell

所以这个读取是在管道之后执行的,这意味着echo的输出被读入str - 但由于它是在管道之后,因此str的内容现在位于父shell无法读取的子shell中.我的问题是 - str的内容会发生什么?管道是否创建子shell,然后一旦内容被读入str,父进程就会终止子进程并删除str - 或者str的内容是否存在于shell之外的某个地方.就像我们如何看待子壳中的内容一样?我们可以从父shell访问子shell吗?

echo hello | read str
echo $str
Run Code Online (Sandbox Code Playgroud)

bash subshell

5
推荐指数
2
解决办法
581
查看次数

为什么子 shell 中的 stderr 没有被抑制或重定向?

我知道子 shell 的标准输出从调用者的输出中被抑制:

a=$(echo 123)
echo a:$a
Run Code Online (Sandbox Code Playgroud)

正如预期的那样,输出:

a:123
Run Code Online (Sandbox Code Playgroud)

但是为什么 stderr 不在子 shell 中被抑制呢?

a=$(>&2 echo 123)
Run Code Online (Sandbox Code Playgroud)

预期输出:

(没有什么)

实际输出:

123
Run Code Online (Sandbox Code Playgroud)

这是一个测试,其中 stderr 应重定向到 stdout 并捕获到变量a

a=$(>&2 echo 123 2>&1)
echo a:$a
Run Code Online (Sandbox Code Playgroud)

预期输出:

a:123
Run Code Online (Sandbox Code Playgroud)

实际输出:

123
a:
Run Code Online (Sandbox Code Playgroud)

bash stderr subshell

5
推荐指数
1
解决办法
3611
查看次数