即使不 export,bash 里再开的 bash(子 bash),也能继承到 PATH 这个 shell 变量,请问,这在平常的脚本编程中有什么用途?不然,bash 为什么这样设计呢?
1
neoblackcap 2018-11-30 22:09:32 +08:00 via iPhone
不是 bash 是这样设计,是 unix 环境下,子进程默认继承父进程的环境变量
|
2
flynaj 2018-11-30 22:39:18 +08:00 via Android
不止 Linux,Windows 也会传环境变量到子进程
|
3
wd 2018-11-30 22:44:31 +08:00 via iPhone
这不是环境变量么,那在这个环境执行的命令不就会继承么?
|
4
WordTian 2018-11-30 22:45:57 +08:00 via Android
要是 path 不继承的话,那子 bash 就没有什么命令可用了
|
5
undeflife 2018-11-30 23:13:20 +08:00
|
6
widewing 2018-12-01 02:37:02 +08:00 via Android
???难道其他变量没有被继承吗?
|
7
binux 2018-12-01 05:05:34 +08:00
PATH 是环境变量不是 shell 变量啊
|
8
dangyuluo 2018-12-01 08:31:50 +08:00
Quote form Wikipedia:
PATH is an environment variable on Unix-like operating systems, DOS, OS/2, and Microsoft Windows, |
9
TonyLiu2ca 2018-12-01 08:49:27 +08:00
man bash
|
10
whileFalse 2018-12-01 08:59:16 +08:00
没有 PATH 跑不起来好吗。
|
11
gowa2017 2018-12-01 09:01:10 +08:00 via iPhone
loginshell fork child bash 采用了 cow 技术 刚开始的时候是共享内存空间的
|
12
iwtbauh 2018-12-01 11:33:04 +08:00 via Android
并没有传给子进程
只是新的 bash 初始化时读取了配置文件然后自己创建了 PATH 变量 请 lz 尝试: unset PATH PATH="foo" /bin/bash echo "$PATH" |
13
lululau 2018-12-01 11:39:33 +08:00
只听说过子进程和子 Shell,子 Bash 是什么鬼
|
14
weyou 2018-12-01 11:53:36 +08:00 via Android
系统启动的时候 PATH 已经是环境变量了,你对它做出的任何修改它还是一个环境变量,所以都会被子进程继承。这有啥奇怪的呢。
|
15
chinvo 2018-12-01 12:03:48 +08:00 via iPhone
你把 foo 塞进系统环境变量里,“不 export ”也能继承。所有已经是环境变量的变量,包括 path、lc_* 等,都是这样的
|
16
cnt2ex 2018-12-01 12:47:34 +08:00
环境变量的传递不是 bash 完成的,是操作系统完成的。在创建子进程的时候操作系统把带有环境变量的那部分内存区域拷贝到子进程的内存完成了环境变量的传递。
|
17
momocraft 2018-12-01 12:57:09 +08:00
先讲清楚你的"子 bash" 是什么东西, 比如附上你用的命令, 我们才能继续讨论环境变量是如何初始化的
|
19
ihainan 2018-12-01 13:07:04 +08:00
还真是这样,这个我都没注意过,习惯性都是加上 export。
|
20
rrfeng 2018-12-01 13:27:55 +08:00
楼主的总结恰好是反的
环境变量会传递给子进程,但是 PATH 恰恰是一个很可能子进程(特别是 bash )会自己重载的环境变量 |
22
weyou 2018-12-01 15:08:30 +08:00 via Android
|
24
autumn2018 OP @jdhao
bash-4.3$ a=1 bash-4.3$ PATH=$PATH:xxx bash-4.3$ echo $PATH /usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:xxx bash-4.3$ echo $a 1 bash-4.3$ bash -norc bash-4.3$ echo $PATH /usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:xxx bash-4.3$ echo $a bash-4.3$ |
25
no1xsyzy 2018-12-01 17:04:17 +08:00
重点不是传递,而是设置 PATH 会直接修改当前环境变量
no1xsyzy@XSY-New:~$ PATH=foo no1xsyzy@XSY-New:~$ bash Command 'bash' is available in '/bin/bash' The command could not be located because '/bin' is not included in the PATH environment variable. bash: command not found 而且其他的只要 export 过后修改也会改变环境变量 no1xsyzy@XSY-New:~$ export a=1 no1xsyzy@XSY-New:~$ a=2 no1xsyzy@XSY-New:~$ /usr/bin/env | /bin/grep "^a=" a=2 所以应该是和 @chinvo #15 说的一样,一个变量一但和环境产生关联就会一直绑定。 |
26
no1xsyzy 2018-12-01 17:19:15 +08:00
help export
help declare | grep -- -x export 不是设置环境变量,而是设置变量类型为导出类型,即这个变量的类型是个环境变量。 export foo=bar 只是个语法糖。 先 export -n PATH 这一现象就会消失。 no1xsyzy@XSY-New:~$ export -n PATH no1xsyzy@XSY-New:~$ PATH=foo no1xsyzy@XSY-New:~$ bash Command 'bash' is available in '/bin/bash' The command could not be located because '/bin' is not included in the PATH environment variable. bash: command not found no1xsyzy@XSY-New:~$ /bin/bash -c 'echo $PATH' /usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:. |
27
iwtbauh 2018-12-01 19:27:00 +08:00 via Android
|
28
weyou 2018-12-01 23:21:44 +08:00 via Android
@jdhao 不管怎么调的,调用了什么,这个问题的答案都是一样的。一个环境变量只要没有被 unset,都会被所有的子进程(本贴中子 bash 也是子进程)继承。就算被修改了也还是环境变量依然会被继承。
|
29
xiaoshenke 2018-12-02 00:18:42 +08:00
因为是环境变量啊 bash 自然是做了特殊处理了
|
30
julyclyde 2018-12-02 10:34:55 +08:00 2
先说结论:
因为 PATH 变量是从上一层继承过来的,默认就是环境变量,所以在 shell 这一层不需要通过 export 命令让它成为环境变量 再说证据: http://git.savannah.gnu.org/cgit/bash.git/tree/execute_cmd.c 的 execute_disk_command 函数里执行了 exit (shell_execve (command, args, export_env)); 其中 export_env 是从 variables.c 里边来的,被 execute_disk_command 调用 shell_execve 之前稍早几句的 maybe_make_export_env (); 写入内容的一个数组 再看 variables.c 文件,maybe_make_export_env 调用了 make_var_export_array,后者又调用了 export_environment_candidate,而最后这个函数只有一句话: return (exported_p (var) && (invisible_p (var) == 0 || imported_p (var))); 关键在于 imported_p。这个 imported_p 并不是个函数而是一个宏,在 variables.h 里定义的,判断条件里的 att_imported 吸引了我。再搜 att_imported,发现 initialize_shell_variables 函数执行的时候会对部分变量标记 att_imported ( att 即 attribute ) 最后说值的继承关系: 在 systemd 为基础的 Linux 发行版里,systemd-exec(5)准备了固定值 PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin 检查 /proc/pid/environ 可以发现,sshd 和 getty 的 PATH 环境变量值均于此一致 |
31
julyclyde 2018-12-02 10:35:41 +08:00
看了看前边的回答,觉得有不少人理解能力有问题
|
32
Kobayashi 2018-12-05 17:32:02 +08:00 via Android
没有 PATH 变量,外部程序去哪里调用……
|
33
momocraft 2018-12-10 10:36:42 +08:00
我又看了一下,PATH 可能是默认就 export 的环境变量 (我机器上用没有.bashrc/.bashprofile 的用户 declare -p PATH 也会看到-x)。
还没有找到这个 export 是在哪个级别决定的 (bash 固定,或哪个全局配置文件)。 |