-
-
Save spacexnasa/925c082b64d5e6a9c380ad7b7d92f9ca to your computer and use it in GitHub Desktop.
Revisions
-
yegle revised this gist
Jan 5, 2012 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -163,5 +163,5 @@ if ((run_by_ssh || isnetconn (fileno (stdin))) && shell_level < 2) [^noa]: Non-option Arguments,即不以`-`开头的参数。例如,`bash -l test.sh`,`-l`是option argument,`test.sh`是non-option argument `[^sysconfdir]`: 严格地说,是`${SYSCONFDIR}/profile`文件。`${SYSCONFDIR}`是程序编译时,传递给`configure`脚本的`--sysconfdir`选项指定的目录。编译时没有指定`--sysconfdir`则使用`--prefix`指定的路径下`etc`文件夹。默认`${SYSCONFDIR}`为`/` [^exception_bashrc]: 存在例外情况。如果编译bash时加上了`#define SYS_BASHRC /etc/bashrc`或`CPPFLAGS`加上了`-DSYS_BASHRC=/etc/bashrc`,那么任何时候`~/.bashrc`被载入前,`${SYS_BASHRC}`文件先被载入 -
yegle revised this gist
Jan 5, 2012 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -56,7 +56,7 @@ Bash启动时会按照一定的顺序载入rc文件,定义`PS1`、`JAVA_HOME` bash会依次执行以下文件 1. `/etc/profile` `[^sysconfdir]` 2. `~/.bash_profile` 3. `~/.bash_login` 4. `~/.profile` @@ -164,4 +164,4 @@ if ((run_by_ssh || isnetconn (fileno (stdin))) && shell_level < 2) [^noa]: Non-option Arguments,即不以`-`开头的参数。例如,`bash -l test.sh`,`-l`是option argument,`test.sh`是non-option argument [^sysconfdir]: 严格地说,是`${SYSCONFDIR}/profile`文件。`${SYSCONFDIR}`是程序编译时,传递给`configure`脚本的`--sysconfdir`选项指定的目录。编译时没有指定`--sysconfdir`则使用`--prefix`指定的路径下`etc`文件夹。默认`${SYSCONFDIR}`为`/` [^exception_bashrc]: 存在例外情况。如果编译bash时加上了`#define SYS_BASHRC /etc/bashrc`或`CPPFLAGS`加上了`-DSYS_BASHRC=/etc/bashrc`,那么任何时候`~/.bashrc`被载入前,`${SYS_BASHRC}`文件先被载入 -
yegle revised this gist
Jan 5, 2012 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -56,7 +56,7 @@ Bash启动时会按照一定的顺序载入rc文件,定义`PS1`、`JAVA_HOME` bash会依次执行以下文件 1. `/etc/profile` `[^sysconfdir]` 2. `~/.bash_profile` 3. `~/.bash_login` 4. `~/.profile` -
keliot revised this gist
Jan 5, 2012 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -67,7 +67,7 @@ bash会依次执行以下文件 ### 非登录/交互Shell 1. “全局”bashrc(编译时定义`SYS_BASHRC`,默认为`/etc/bash.bashrc`) 2. `~/.bashrc` [^exception_bashrc] ## SSH远程登录服务器执行命令场景分析 -
keliot revised this gist
Jan 5, 2012 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -67,8 +67,8 @@ bash会依次执行以下文件 ### 非登录/交互Shell 1. `SYS_BASHRC`(编译时定义,默认为`/etc/bash.bashrc`) 2. `~/.bashrc` [^exception_bashrc] ## SSH远程登录服务器执行命令场景分析 -
keliot revised this gist
Jan 5, 2012 . 1 changed file with 22 additions and 5 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -67,7 +67,8 @@ bash会依次执行以下文件 ### 非登录/交互Shell 执行`SYS_BASHRC`(编译时定义,默认为`/etc/bash.bashrc`) 执行`~/.bashrc`文件 [^exception_bashrc] ## SSH远程登录服务器执行命令场景分析 @@ -77,7 +78,7 @@ bash会依次执行以下文件 使用的命令为`ssh 127.0.0.1 w`进行分析,会发现这个命令执行时会载入`~/.bashrc`,不会载入`/etc/profile`等文件 在`~/.bashrc`文件中放置命令`ps -p $$ -o args=`,可获得载入`~/.bashrc`文件的进程命令行为`bash -c w`,是一个非登录、非交互Shell。根据`bash(1)`中`INVOCATION`段的说明,此时应该只载入`$BASH_ENV`环境变量的脚本,不会载入`/etc/bash.bashrc`或`~/.bashrc`脚本 进一步研究OpenSSH源码和Bash源码。OpenSSH中执行shell部分的代码如下: @@ -99,7 +100,21 @@ exit(1); 而Bash中的相关代码: ```c // from config-top.h /* Define this if you want bash to try to check whether it's being run by sshd and source the .bashrc if so (like the rshd behavior). */ /* #define SSH_SOURCE_BASHRC */ // from shell.c of Bash 4.2 #ifdef SSH_SOURCE_BASHRC run_by_ssh = (find_variable ("SSH_CLIENT") != (SHELL_VAR *)0) || (find_variable ("SSH2_CLIENT") != (SHELL_VAR *)0); #else /* ... */ /* If we were run by sshd or we think we were run by rshd, execute ~/.bashrc if we are a top-level shell. */ if ((run_by_ssh || isnetconn (fileno (stdin))) && shell_level < 2) @@ -116,9 +131,11 @@ if ((run_by_ssh || isnetconn (fileno (stdin))) && shell_level < 2) } ``` 可以看到,只要编译前在`config-top.h`中定义`SSH_SOURCE_BASHRC`,那么尽管Bash在被sshd fork出来的时候加上了`-c`选项,也确实是non-login non-interactive shell,只要发现`SSH_CLIENT`或者`SSH2_CLIENT`环境变量存在,就仍然会依次载入`SYS_BASHRC`、`~/.bashrc`文件。 这个结论非常重要,因为包括svn、git、rsync在内很多命令都使用ssh作为传输层。如果`/etc/bash.bashrc`、`~/.bashrc`文件配置不合理,这些命令的执行都会有问题。 请注意,在此问题上,各发行版自带bash的行为可能不同。Debian 5和6的补丁都设置了`SSH_SOURCE_BASHRC`,用户自己编译时可能未设定,因此也不能简单地认为通过ssh执行命令时服务器上的bash一定载入bashrc系列文件,更不可依赖bashrc来执行初始化命令。 ## 常见问题分析 @@ -147,4 +164,4 @@ if ((run_by_ssh || isnetconn (fileno (stdin))) && shell_level < 2) [^noa]: Non-option Arguments,即不以`-`开头的参数。例如,`bash -l test.sh`,`-l`是option argument,`test.sh`是non-option argument [^sysconfdir]: 严格地说,是`${SYSCONFDIR}/profile`文件。`${SYSCONFDIR}`是程序编译时,传递给`configure`脚本的`--sysconfdir`选项指定的目录。编译时没有指定`--sysconfdir`则使用`--prefix`指定的路径下`etc`文件夹。默认`${SYSCONFDIR}`为`/` [^exception_bashrc]: 存在例外情况。如果编译bash时加上了`#define SYS_BASHRC /etc/bashrc`或`CPPFLAGS`加上了`-DSYS_BASHRC=/etc/bashrc`,那么任何时候`~/.bashrc`被载入前,`${SYS_BASHRC}`文件先被载入 -
yegle revised this gist
Jan 5, 2012 . 1 changed file with 7 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -19,9 +19,12 @@ Login Shell的定义是,当前shell的`argv[0]`的第一个字符是`-`,或 2. 执行`su -l admin` ( 运行的Shell的`argv[0]`第一个字符是`-` ) 3. 执行`login -f` ( 运行的Shell的`argv[0]`第一个字符是`-` ) 4. 将当前目录加入到`$PATH`,根据以下命令创建到bash的链接并执行 ( 运行的Shell的`argv[0]`第一个字符是`-` ) ```bash export PATH=".:$PATH" ln -s -- $(which bash) -bash -bash ``` ### 交互与非交互Shell @@ -126,7 +129,7 @@ if ((run_by_ssh || isnetconn (fileno (stdin))) && shell_level < 2) ### 在`~/.bashrc`文件是否能`source ~/.bash_profile`呢? 以前遇到过一个问题。跳板机上在`~/.bashrc`里显示了一些banner信息,导致诡异地无法从其他服务器`rsync`文件到这台跳板机上。 从`rsync(1)`的`DIAGNOSTICS`部分可以看到,`rsync`非常依赖于shell执行时没有任何输出。如果在`~/.bashrc`中source了`~/.bash_profile`,而`~/.bash_profile`中又有无关的文字输出,就会导致从其他服务器rsync到此服务器失败,报错信息为"protocol version mismatch — is your shell clean?"。这也回答了上一节的问题:*banner类信息不能放在`~/.bashrc`文件内* -
yegle revised this gist
Jan 5, 2012 . 1 changed file with 31 additions and 31 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -78,40 +78,40 @@ bash会依次执行以下文件 进一步研究OpenSSH源码和Bash源码。OpenSSH中执行shell部分的代码如下: ```c // from session.c of OpenSSH 5.9p1 /* * Execute the command using the users shell. This uses the -c * option to execute the command. */ argv[0] = (char *) shell0; argv[1] = "-c"; argv[2] = (char *) command; argv[3] = NULL; execve(shell, argv, env); perror(shell); exit(1); ``` 而Bash中的相关代码: ```c // from shell.c of Bash 4.2 /* If we were run by sshd or we think we were run by rshd, execute ~/.bashrc if we are a top-level shell. */ if ((run_by_ssh || isnetconn (fileno (stdin))) && shell_level < 2) { #ifdef SYS_BASHRC # if defined (__OPENNT) maybe_execute_file (_prefixInstallPath(SYS_BASHRC, NULL, 0), 1); # else maybe_execute_file (SYS_BASHRC, 1); # endif #endif maybe_execute_file (bashrc_file, 1); return; } ``` 可以看到,Bash在被sshd fork出来的时候加上了`-c`选项,确实是non-login non-interactive shell,但是仍然会载入`~/.bashrc`文件。 -
yegle revised this gist
Jan 5, 2012 . 1 changed file with 11 additions and 8 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,17 +1,18 @@ # Bash Shell启动方式与rc脚本 ## Shell的不同分类 根据启动Bash Shell的方式不同,对Shell有两种分类方式 ### 登录Shell与非登录Shell 根据Shell的启动方式不同,可以将Shell分为 1. Login Shell 2. Non-login Shell Login Shell的定义是,当前shell的`argv[0]`的第一个字符是`-`,或当前shell使用了`-l` ( `--login` ) 选项。 只要满足以上的两个条件的任意一个,bash就会表现得Login Shell一样。例如,以下列出的场景下,bash都是login shell: 1. 执行`bash -l -c 'w'` ( 使用了-l选项 ) @@ -77,7 +78,7 @@ bash会依次执行以下文件 进一步研究OpenSSH源码和Bash源码。OpenSSH中执行shell部分的代码如下: ```c // from session.c of OpenSSH 5.9p1 /* * Execute the command using the users shell. This uses the -c @@ -90,10 +91,11 @@ bash会依次执行以下文件 execve(shell, argv, env); perror(shell); exit(1); ``` 而Bash中的相关代码: ```c // from shell.c of Bash 4.2 /* If we were run by sshd or we think we were run by rshd, execute ~/.bashrc if we are a top-level shell. */ @@ -109,6 +111,7 @@ bash会依次执行以下文件 maybe_execute_file (bashrc_file, 1); return; } ``` 可以看到,Bash在被sshd fork出来的时候加上了`-c`选项,确实是non-login non-interactive shell,但是仍然会载入`~/.bashrc`文件。 @@ -141,4 +144,4 @@ SA组内部以前遇到过一个问题。跳板机上在`~/.bashrc`里显示了 [^noa]: Non-option Arguments,即不以`-`开头的参数。例如,`bash -l test.sh`,`-l`是option argument,`test.sh`是non-option argument [^sysconfdir]: 严格地说,是`${SYSCONFDIR}/profile`文件。`${SYSCONFDIR}`是程序编译时,传递给`configure`脚本的`--sysconfdir`选项指定的目录。编译时没有指定`--sysconfdir`则使用`--prefix`指定的路径下`etc`文件夹。默认`${SYSCONFDIR}`为`/` [^exception_bashrc]: 存在例外情况。如果编译bash时加上了`#define SYS_BASHRC /etc/bashrc`或`CPPFLAGS`加上了`-DSYS_BASHRC=/etc/bashrc`,那么任何时候`~/.bashrc`被载入前,`${SYS_BASHRC}`文件先被载入 -
There are no files selected for viewing
File renamed without changes. -
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,144 @@ # Bash Shell启动方式与rc脚本 [TOC] *** ## Shell的不同分类根据启动Bash Shell的方式不同,对Shell有两种分类方式 ### 登录Shell与非登录Shell 根据Shell的启动方式不同,可以将Shell分为 1. Login Shell2. Non-login Shell Login Shell的定义是,当前shell的`argv[0]`的第一个字符是`-`,或当前shell使用了`-l` ( `--login` ) 选项。 只要满足以上的两个条件的任意一个,bash就会表现得Login Shell一样。例如,以下列出的场景下,bash都是login shell: 1. 执行`bash -l -c 'w'` ( 使用了-l选项 ) 2. 执行`su -l admin` ( 运行的Shell的`argv[0]`第一个字符是`-` ) 3. 执行`login -f` ( 运行的Shell的`argv[0]`第一个字符是`-` ) 4. 将当前目录加入到`$PATH`,根据以下命令创建到bash的链接并执行 ( 运行的Shell的`argv[0]`第一个字符是`-` ) :::bash export PATH=".:$PATH" ln -s -- $(which bash) -bash -bash ### 交互与非交互Shell 同时,根据Shell启动参数的不同,还可以将Shell分为 1. Interactive Shell 2. Non-interactive Shell Interactive Shell的定义很明确:`$-`环境变量中包含字符`i`的Shell就是Interactive Shell 以下场景中,bash属于Interactive Shell 1. bash执行时没有加上非选项参数 [^noa] 2. bash执行时没有加上`-c`选项 3. bash执行时,加上了`-i`选项 以下场景中,bash属于Non-interactive Shell 1. 使用`rsync -e ssh`同步文件(`-c`选项) 2. 其他基于ssh的文件传输,如git、svn等(基本都启用了`-c`选项) ## 不同Shell中启动时执行的文件 Bash启动时会按照一定的顺序载入rc文件,定义`PS1`、`JAVA_HOME`等环境变量,执行特定的脚本等。 按照两种Shell分类排列组合,一共有4种组合。各个组合下启动载入rc文件的顺序和数量有区别,以下分别列出: ### 登录/非交互Shell & 登录/交互Shell bash会依次执行以下文件 1. `/etc/profile` [^sysconfdir] 2. `~/.bash_profile` 3. `~/.bash_login` 4. `~/.profile` ### 非登录/非交互Shell 执行`$BASH_ENV`环境变量中指定的脚本 ### 非登录/交互Shell 仅会执行`~/.bashrc`文件 [^exception_bashrc] ## SSH远程登录服务器执行命令场景分析 上面在分析交互/非交互、登录/非登录Shell的时候,特地省略了ssh到远程服务器执行命令这种场景下Shell类型的分类,放在这里分析。 相关的资料不是很多,不管是`bash(1)`还是`ssh(1)`还是`sshd(1)`,都没有对这个场景详细说明过。经过多次尝试,在不同的rc文件里echo特定字符串,得出结论。如果分析有问题,请大家纠正。 使用的命令为`ssh 127.0.0.1 w`进行分析,会发现这个命令执行时会载入`~/.bashrc`,不会载入`/etc/profile`等文件 在`~/.bashrc`文件中放置命令`ps -p $$ -o args=`,可获得载入`~/.bashrc`文件的进程命令行为`bash -c w`,是一个非登录、非交互Shell。根据`bash(1)`中`INVOCATION`段的说明,此时应该只载入`$BASH_ENV`环境变量的脚本,不会载入`~/.bashrc`脚本 进一步研究OpenSSH源码和Bash源码。OpenSSH中执行shell部分的代码如下: :::c // from session.c of OpenSSH 5.9p1 /* * Execute the command using the users shell. This uses the -c * option to execute the command. */ argv[0] = (char *) shell0; argv[1] = "-c"; argv[2] = (char *) command; argv[3] = NULL; execve(shell, argv, env); perror(shell); exit(1); 而Bash中的相关代码: :::c // from shell.c of Bash 4.2 /* If we were run by sshd or we think we were run by rshd, execute ~/.bashrc if we are a top-level shell. */ if ((run_by_ssh || isnetconn (fileno (stdin))) && shell_level < 2) { #ifdef SYS_BASHRC # if defined (__OPENNT) maybe_execute_file (_prefixInstallPath(SYS_BASHRC, NULL, 0), 1); # else maybe_execute_file (SYS_BASHRC, 1); # endif #endif maybe_execute_file (bashrc_file, 1); return; } 可以看到,Bash在被sshd fork出来的时候加上了`-c`选项,确实是non-login non-interactive shell,但是仍然会载入`~/.bashrc`文件。 这个结论非常重要,因为包括svn、git、rsync在内很多命令都使用ssh作为传输层。如果`~/.bashrc`文件配置不合理,这些命令的执行都会有问题。 ## 常见问题分析 ### Banner、Motd类提示信息应该放在哪里? 某些服务器可以在用户登录时加入一些提示信息,提示用户操作等。这样的信息仅需要在用户登录时显示,因此可以将此类信息放在login shell才会载入的文件中,如`/etc/profile`、`~/.bash_profile`、`~/.bash_login`、`~/.profile` 是否能将此类提示信息放在`~/.bashrc`文件内呢?下面说明 ### 在`~/.bashrc`文件是否能`source ~/.bash_profile`呢? SA组内部以前遇到过一个问题。跳板机上在`~/.bashrc`里显示了一些banner信息,导致诡异地无法从其他服务器`rsync`文件到这台跳板机上。 从`rsync(1)`的`DIAGNOSTICS`部分可以看到,`rsync`非常依赖于shell执行时没有任何输出。如果在`~/.bashrc`中source了`~/.bash_profile`,而`~/.bash_profile`中又有无关的文字输出,就会导致从其他服务器rsync到此服务器失败,报错信息为"protocol version mismatch — is your shell clean?"。这也回答了上一节的问题:*banner类信息不能放在`~/.bashrc`文件内* 但是反过来,在`~/.bash_profile`中`source ~/.bashrc`是可以的,但是使用时要非常小心(容易引起循环引用,导致问题) ### ssh到服务器执行`java -version`为什么版本和实际应用使用的不一致? 目前`JAVA_HOME`、`PATH`等环境变量的定义是在`/etc/profile`。ASA比较常见的操作是脚本跑一个集群,ssh到相应服务器上确认java版本是否正确。这个时候shell只会载入`~/.bashrc`,不会载入`/etc/profile`。 解决方法可以用以下任一: * 先`source /etc/profile`再执行`java -version`来判断 * 执行 `ssh remote-host 'bash -l -c "java -version"'` [^noa]: Non-option Arguments,即不以`-`开头的参数。例如,`bash -l test.sh`,`-l`是option argument,`test.sh`是non-option argument [^sysconfdir]: 严格地说,是`${SYSCONFDIR}/profile`文件。`${SYSCONFDIR}`是程序编译时,传递给`configure`脚本的`--sysconfdir`选项指定的目录。编译时没有指定`--sysconfdir`则使用`--prefix`指定的路径下`etc`文件夹。默认`${SYSCONFDIR}`为`/` [^exception_bashrc]: 存在例外情况。如果编译bash时加上了`#define SYS_BASHRC /etc/bashrc`或`CPPFLAGS`加上了`-DSYS_BASHRC=/etc/bashrc`,那么任何时候`~/.bashrc`被载入前,`${SYS_BASHRC}`文件先被载入