相关疑难解决方法(0)

如果进程继承了父级的环境,为什么还需要导出?

在这里读到,export在 shell中的目的是使变量可用于从 shell 启动的子进程。

但是,我也看到了这里,并在这里的“进程从它们的父(这开始它们的进程)继承他们的环境。”

如果是这种情况,我们为什么需要export?我错过了什么?

默认情况下,shell 变量不是环境的一部分吗?有什么不同?

shell process environment-variables

94
推荐指数
3
解决办法
6万
查看次数

如何检测我是否在子shell中?

我正在尝试编写一个函数来替换exit内置函数的功能,以防止自己退出终端。

我曾尝试使用SHLVL环境变量,但它在子外壳中似乎没有改变:

$ echo $SHLVL
1
$ ( echo $SHLVL )
1
$ bash -c 'echo $SHLVL'
2
Run Code Online (Sandbox Code Playgroud)

我的功能如下:

exit () {
    if [[ $SHLVL -eq 1 ]]; then
        printf '%s\n' "Nice try!" >&2
    else
        command exit
    fi
}
Run Code Online (Sandbox Code Playgroud)

不过,这不允许我exit在子外壳中使用:

$ exit
Nice try!
$ (exit)
Nice try!
Run Code Online (Sandbox Code Playgroud)

检测我是否在子shell中的好方法是什么?

shell bash exit subshell

32
推荐指数
3
解决办法
6316
查看次数

我可以让 cd 成为函数的本地吗?

是否可以制作一个类似的功能

function doStuffAt {
    cd $1
    # do stuff
}
Run Code Online (Sandbox Code Playgroud)

但是让它如此调用该函数实际上并没有改变我的密码,它只是在函数的持续时间内改变它?我知道我可以保存密码并在最后设置它,但我希望有一种方法可以让它在本地发生而不必担心。

bash shell-script shell-builtin

27
推荐指数
4
解决办法
2674
查看次数

为什么变量在子shell中可见?

Learning Bash Book 提到一个子shell只会继承环境变量和文件描述符等,不会继承没有导出的变量:

$ var=15
$ (echo $var)
15
$ ./file # this file include the same command echo $var

$
Run Code Online (Sandbox Code Playgroud)

据我所知,shell 将为()和 for创建两个子shell ./file,但是为什么在这种()情况下,子shell 会识别var变量,尽管它没有导出,而在这种./file情况下它没有识别?

# Strace for () 
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f24558b1a10) = 25617
# Strace for ./file
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f24558b1a10) = 25631
Run Code Online (Sandbox Code Playgroud)

我试图strace弄清楚这是如何发生的,令人惊讶的是我发现 bash 将对克隆系统调用使用相同的参数,所以这意味着分叉进程()./file应该具有与父进程相同的进程地址空间,那么为什么在这种()情况下,变量是否对子外壳可见,并且这种情况不会发生./file,尽管相同的参数基于克隆系统调用?

shell bash subshell

20
推荐指数
2
解决办法
2898
查看次数

“子外壳”和“子进程”之间的确切区别是什么?

根据thisthis,子shell是通过使用括号启动的(…)

( echo "Hello" )
Run Code Online (Sandbox Code Playgroud)

根据this , thisthis,当命令以&

echo "Hello" &
Run Code Online (Sandbox Code Playgroud)

Posix 规范在本页中使用了这个词subshell但没有定义它,而且,在同一页上,也没有定义“子进程”

两者都使用核fork()函数,对吗?

那么将一些叉称为“子外壳”而将其他一些叉称为“子进程”的确切区别是什么。

shell bash subshell

20
推荐指数
2
解决办法
7426
查看次数

如何获取子shell的pid?

如何获取子shell的pid?

例如:

$ echo $$
16808
Run Code Online (Sandbox Code Playgroud)

这不起作用,因为原始外壳扩展$$

$ ( echo $$ )
16808
Run Code Online (Sandbox Code Playgroud)

为什么单引号不起作用?原shell去掉单引号后,子shell$$自己不展开了吗?

$ ( echo '$$' )
$$
Run Code Online (Sandbox Code Playgroud)

为什么也eval不起作用?是eval由子shell 运行的吗?为什么它会给我原始外壳的 PID?

$ ( eval echo '$$' )
16808
Run Code Online (Sandbox Code Playgroud)

谢谢。

bash process subshell

17
推荐指数
2
解决办法
8584
查看次数

子壳和子壳是一样的吗

有这两个名称:subshel​​lchild-shell

是的,子进程将通过以下任一方式启动:

sh -c 'echo "Hello"'
( echo "hello" )
echo "$(echo "hello")
echo "hello" | cat
Run Code Online (Sandbox Code Playgroud)

是否全部相同并共享相同的名称?所有共享相同的属性吗?


POSIX有这个定义

一个shell执行环境包括....

但是上面链接的最后一段是这样的:

子shell 环境应创建为shell 环境的副本,除了未被忽略的信号陷阱应设置为默认操作。

特别是:

命令替换、用括号分组的命令和异步列表应在子 shell 环境中执行。另外,多命令管道的每个命令都在一个子shell环境中;....

sh -c 'echo "Hello"'不包括有,应该是可以称为子shell?

shell bash process posix subshell

14
推荐指数
1
解决办法
4161
查看次数

命令替换子shell中的bash变量可见性

我正在阅读一本 Linux shell 脚本书,并发现以下警告:

“命令替换会创建所谓的子外壳来运行封闭的命令。子外壳是从运行脚本的外壳生成的单独子外壳。因此,您在脚本中创建的任何变量都不能用于子外壳命令”。

我尝试在当前 bash shell 的 CLI 中创建一个变量,然后进入子 shell 检查是否可以在屏幕上打印它。所以是的,我做不到,似乎是根据上面的引文。但是,我已经使用命令替换运行了以下脚本:

#!/bin/bash
var=5.5555
ans=$(echo $var)
echo $ans
Run Code Online (Sandbox Code Playgroud)

结果是:

5.5555
Run Code Online (Sandbox Code Playgroud)

据我了解,它不应该打印 var 的值,因为子外壳不应该能够“看到它”。为什么会发生?

shell bash

8
推荐指数
2
解决办法
8955
查看次数

在 bash 中创建子shell的所有方法是什么?

到目前为止,我知道有两种主要方式:

  • 显式:将括号括在命令列表中

  • 隐式:管道中的每个命令

是否有更多的方式,无论是显式还是隐式,在 bash 中创建子shell?

bash subshell

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

为什么 (...) 在后台运行时不会产生新的子进程?

运行命令后

{ sleep 5; } &  
Run Code Online (Sandbox Code Playgroud)

输出ps是(输出1)

 PID TTY           TIME CMD
  972 ttys000    0:00.27 -bash
 2556 ttys000    0:00.00 -bash
 2557 ttys000    0:00.00 sleep 5   
Run Code Online (Sandbox Code Playgroud)

而对于

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

ps是(输出 2)

PID TTY           TIME CMD
 972 ttys000    0:00.28 -bash
2566 ttys000    0:00.00 sleep 5  
Run Code Online (Sandbox Code Playgroud)

()导致子shell环境,我希望在这种情况下为“输出1”,因为它会导致子进程分叉,而我希望{ sleep 5; } &在当前shell中执行时为“输出2” 。这可能看起来是一个愚蠢的问题,但我真的不明白这种行为。
我在这里缺少什么?

bash command subshell

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

bash 命令替换与变量中字符串命令的行为

$ echo $(echo x; echo y)
x y
$ a='echo x; echo y'
$ echo $($a)  # expect 'x y'
x; echo y
Run Code Online (Sandbox Code Playgroud)
  1. 为什么命令替换会以这种方式运行?
  2. 如何在不使用eval和的情况下对存储在变量中的命令列表执行命令替换bash -c

echo $(eval $a)并且echo $(bash -c "$a")实际上做了我想要的,但我听说使用 eval 经常是解决问题的错误方法,所以我想知道如何在没有这些命令的情况下进行管理(使用bash -c实际上是一样的)

command-line bash command-substitution variable-substitution

4
推荐指数
2
解决办法
3197
查看次数

进程标志 1:分叉但没有执行(用例?)

在 ps 的手册页中,它将进程标志 1 列为“进程分叉但未执行”。进程处于这种状态的常见用例/情况是什么?

process fork

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