[Topic DIscussion] 为什么`$SHELL`命令会导致当前命令窗口只输出错误内容?
Tofloor
poster avatar
momen
deepin
2022-10-09 19:37
Author

众所周知,反引号是会把里面的内容当命令执行

那么我们输入以下内容 `$SHELL`

结果发现当前的窗口无论输入什么命令都只会输入错误内容

效果类似于 [命令] > /dev/null

这是为什么呢?

confused

Reply Favorite View the author
All Replies
momen
deepin
2022-10-09 19:42
#1
Reply View the author
魔法师
deepin
2022-10-09 19:55
#2
  1. $SHELL 指向 /bin/bash

  2. `$SHELL`   所执行的是 /bin/bash 的输出结果
    

    因为 bash 一出现就直接就有特殊符号所以命令基本上会执行失败,并不是输出内容 >> /dev/null 了,而是进入了管子(道),准备返回给上层,大概率会将 子bash的输入内容返回到上层。
    image.png

Reply View the author
忘记、过去
deepin
2022-10-09 20:17
#3
It has been deleted!
momen
deepin
2022-10-09 20:18
#4
It has been deleted!
momen
deepin
2022-10-09 20:18
#5
魔法师
  1. $SHELL 指向 /bin/bash

  2. `$SHELL`   所执行的是 /bin/bash 的输出结果
    

    因为 bash 一出现就直接就有特殊符号所以命令基本上会执行失败,并不是输出内容 >> /dev/null 了,而是进入了管子(道),准备返回给上层,大概率会将 子bash的输入内容返回到上层。
    image.png

命令还是会执行的,比如你mkdir一个文件夹,他真的会创建,但如果创建的是同名文件夹他会立即返回错误值。

或者你离线apt update一下(这样既有正确信息又有错误信息,方便看)

不过我没用exit,看起来,确实是执行了子bash,但我不理解为什么错误信息回立即返回上来,等退出后再反上来正确信息。

Reply View the author
momen
deepin
2022-10-09 20:38
#6

我好像明白了,这个输出效果类似

`[命令]`

那么也就是说,我创建了一个bash子进程,无论输入什么命令都自动套了个反引号

Reply View the author
wtz
deepin
2022-10-09 20:44
#7
momen

命令还是会执行的,比如你mkdir一个文件夹,他真的会创建,但如果创建的是同名文件夹他会立即返回错误值。

或者你离线apt update一下(这样既有正确信息又有错误信息,方便看)

不过我没用exit,看起来,确实是执行了子bash,但我不理解为什么错误信息回立即返回上来,等退出后再反上来正确信息。

可能开启子shell时默认只捕捉stdout,不捕捉stderr?

有些程序内部可能也会判断一下stdout的性质(物理显示器或重定向buffer),并决定是否输出提示信息。

如果是

`$SHELL 2>&1`

的话就啥也没有了。

Reply View the author
deepinuser17
deepin
2022-10-09 21:09
#8

$SHELL是系统为用户设定的默认环境变量。 这个环境变量是从用户账户指定的shell获得。 是打开终端时的默认环境变量。可以直接调用。

用户可以在当前的终端修改所使用的shell. 修改shell以后,$SHELL会指向当前设置的shell.

Reply View the author
lanxing0821
deepin
2022-10-09 21:11
#9

下面是命令替换 $(command) 的相关定义,以供参考:
执行扩展时,shell 在子 shell 环境中执行 command ,同时将 command 的标准输出关联到当前 shell (父 shell)的某个管道上。 shell 会从该管道中读取数据,并用读到的数据来替换命令 command

执行 $($SHELL) 时,如上所述,新建的 shell 的标准输出已经关联到了父 shell 的某个管道上,而不是终端,所以命令的标准输出不会在终端中显示出来。当然,你也可以通过将所执行命令的标准输出重定向到标准错误来显示命令的输出,比如下面的命令可以在标准错误中查看子 shell 的文件描述符关联状态:

ls -l /proc/$$/fd >&2

需要将当前 shell (子 shell )的标准输出关联到终端时,执行:

exec 1<>/dev/stdin
Reply View the author
momen
deepin
2022-10-09 21:13
#10

二楼给了我一些新的想法

image.png

又有一些思路

`$SHELL` 命令,创建了一个子bash进程,子bash里面执行的内容作为结果,并结合前面的命令再次输出

image.png

Reply View the author
momen
deepin
2022-10-09 21:15
#11
lanxing0821

下面是命令替换 $(command) 的相关定义,以供参考:
执行扩展时,shell 在子 shell 环境中执行 command ,同时将 command 的标准输出关联到当前 shell (父 shell)的某个管道上。 shell 会从该管道中读取数据,并用读到的数据来替换命令 command

执行 $($SHELL) 时,如上所述,新建的 shell 的标准输出已经关联到了父 shell 的某个管道上,而不是终端,所以命令的标准输出不会在终端中显示出来。当然,你也可以通过将所执行命令的标准输出重定向到标准错误来显示命令的输出,比如下面的命令可以在标准错误中查看子 shell 的文件描述符关联状态:

ls -l /proc/$$/fd >&2

需要将当前 shell (子 shell )的标准输出关联到终端时,执行:

exec 1<>/dev/stdin

嗯嗯,实践一下确实如此

Reply View the author
momen
deepin
2022-10-09 21:20
#12
lanxing0821

下面是命令替换 $(command) 的相关定义,以供参考:
执行扩展时,shell 在子 shell 环境中执行 command ,同时将 command 的标准输出关联到当前 shell (父 shell)的某个管道上。 shell 会从该管道中读取数据,并用读到的数据来替换命令 command

执行 $($SHELL) 时,如上所述,新建的 shell 的标准输出已经关联到了父 shell 的某个管道上,而不是终端,所以命令的标准输出不会在终端中显示出来。当然,你也可以通过将所执行命令的标准输出重定向到标准错误来显示命令的输出,比如下面的命令可以在标准错误中查看子 shell 的文件描述符关联状态:

ls -l /proc/$$/fd >&2

需要将当前 shell (子 shell )的标准输出关联到终端时,执行:

exec 1<>/dev/stdin

确实是起到拼接的作用image.png

Reply View the author
liwl
deepin
2022-10-09 21:44
#13

没事不要瞎搞大兄弟,环境搞好,就开始搬砖了,社会主义等着我去建设

applaud

Reply View the author