本文共 2671 字,大约阅读时间需要 8 分钟。
Linux shell脚本编程大全
不同模式运行,自然加载的环境变量就不同,command not found 就是因为PATH环境变量不正确导致命令找不到,由于cron是一种非登录非交互模式运行,PATH环境变量只有少量的路径
用户登录机器获得的shell自然就是登录和交互的shell,想一想,你是不是需要登入,并且你这个shell是不是执行一条命令,它就给你反馈一个结果。
当登入Linux系统时,bash shell会作为登入shell启动。同时会从下面的5个不同的启动文件读取命令:
shell会按照按照下列顺序,运行第一个被找到的文件,余下的则被忽略:
CentOS Linux系统中的.bash_profile有一个 . ~/.bashrc 它会去检查是否存在这个文件,如果有先执行这个文件
1. bash -l yourshell.sh2. #!/bin/bash --login 脚本的开头
如果你的bash shell不是登录系统时启动的(比如是在命令行提示符下敲入bash时启动),那 么你启动的shell叫作交互式shell。交互式shell不会像登录shell一样运行,但它依然提供了命令行 提示符来输入命令。
如果bash是作为交互式shell启动的,它就不会访问/etc/profile文件,只会检查用户HOME目录 中的.bashrc文件,在这个文件中会调用/etc/bashrc。
.bashrc文件有两个作用:一是查看/etc目录下通用的bashrc文件,二是为用户提供一个定制自 己的命令别名
为了处理这种情况, bash shell提供了BASH_ENV环境变量。当shell启动一个非交互式shell进程时,它会检查这个环境变量来查看要执行的启动文件。如果有指定的文件, shell会执行该文件里的命令,这通常包括shell脚本变量设置。
那如果BASH_ENV变量没有设置(通常都没有设置可以通过echo $BASH_ENV 查看), shell脚本到哪里去获得它们的环境变量呢?别忘了有些 shell脚本是通过启动一个子shell来执行的。子shell可以继承父shell导出过的变量。
举例来说,如果父shell是登录shell,在/etc/profile、 /etc/profile.d/*.sh和$HOME/.bashrc文件中设置并导出了变量,用于执行脚本的子shell就能够继承这些变量。要记住,由父shell设置但并未导出的变量都是局部变量。子shell无法继承局部变量。对于那些不启动子shell的脚本,变量已经存在于当前shell中了。所以就算没有设置BASH_ENV,也可以使用当前shell的局部变量和全局变量
通过我的不断尝试,在每个配置文件中加入 echo /etc/profile(不同文件名不同) >> /home/splend/env.out 观察发现。通过设置BASH_ENV source等方式,这些文件确实有加载,但是你如果加上echo $PATH >> /home/splend/env.out 会发现,在加载第一个/etc/profile的时候PATH已经是一大串的路径了。
也就是login shell根本在执行/etc/profile之前 PATH已经是一大堆了。而cron执行的是非登录,非交互的,在执行/etc/profile BASH_ENV指定的也好 source指定的也好,你会发现PATH就两个路径(我的是这样)
1.echo $- 如果是himBHs其中出现i说明是交互的 2.echo $PS1 如果不是空说明是登入的
通过一次运行cron脚本出现的问题,然后翻阅shell脚本编程,外加自己不断傻傻的一个一个文件查看PATH的变化,最后才发现在加载这些对应的文件之前就把PATH限定了,如果后面不直接加入PATH的话还是不行,在不断尝试的过程中,以为应该把这个定时脚本用 bash -li my_script.sh强行指定为登录交互式应该就能和正常登入用的shell一样的PATH了吧,然而并不可以。
转载地址:http://xdzvi.baihongyu.com/