背景
今天在做一个事情的时候,出现一个问题。 我使用java程序通过ssh登录到一台linux机器,使用hadoop命令hadoop fs -get /xxx /xxx时,结果报错如下
bash command hadoop not found
而我登录机器执行的时候没有问题。
排查如下:
- 在命令中加入
source /etc/profile执行可行
原因
使用sshj 登录机器的时候没有读到/etc/profile内容。
根本原因:使用java程序登录机器的时候,登录的为non-login shell, non-login shell不会读取/etc/profile的内容。
login shell 和 non-login shell的区别
login shell:打开bash时需要完整的登录流程。就是说通过输入账号和密码登录系统,此时取得的shell称为login shell
non-login shell:取得bash接口的方法不需要重复登录的举动。例如:以X Window登录登录linux后,再以X的图形界面启动终端机,此时那个终端机并没有需要输入账号和密码,那个bash环境就是non-login shell。在原本的bash环境下再次执行bash命令,同样也没有输入账号密码就进入新的bash环境(前一个bash的子进程),新的bash也是non-login shell。
区别:
login shell:此种方式登录时,shell会重新读取/etc/profile和~/.bash_profile来应用新的环境变量。
non-login shell:此时shell不会读取/etc/profile和~/.bash_profile,而是读取~/.bashrc来应用新的环境变量。
PS1:bash在读取/etc/profile后会读取各账户的个人配置文件,所读取的个人配置文件主要有三个:~/.bash_profile, ~/.bash_login, ~/.profile。
其实bash在读取的时候只会读取的上述三个文件的其中一个(可能会加载别的配置文件,如~./profile 加载的是~/.bashrc),而读取的顺序则就是上面的顺序。也就是说bash会依次查找上述三个个人配置文件,且找到一个后,后续的文件便不再读取。
PS2:
Login Shell
初始化脚本加载顺序如下:
1. /etc/profile,/etc/profile.d/*
2. $HOME/.bash_profile,$HOME/.bashrc,/etc/bashrc或者/etc/bash.bashrc
3. $HOME/.bash_login
4. $HOME/.profile
同一行内多个脚本是表示后面的脚本被包含在前面的脚本中得到加载。
Non-Login Shell
可理解为开头部分描述的interactive shell
初始化脚本加载顺序如下:
1. $HOME/.bashrc,/etc/bashrc或者/etc/bash.bashrc,/etc/profile.d/*