3shell 脚本的执行原理
当执行一个命令的时候, 先判断是不是别名, 内部命令. 如果不是就看是否是外部命令, 外部命令是对应 PATH 变量的路径来找的.
在 Linux 里面, 执行命令是不会寻找当前目录的
而当 shell 脚本运行时, 它会先查找系统环境变量 ENV 里面的 PATH 路径.
该变量指定了环境文件(加载顺序一般默认是 / etc/profile,.bash profile.,~/.bashrc, /etc/bashrc 等), 在加载了上述环境变量文件后, shell 就开始执行 shell 脚本中的内容.
shell 脚本是从上至下, 从左至右依次执行每一行的命令及语句的, 即执行完了一个命令后再执行下一个.
如果在 shell 脚本中遇到子脚本 (即脚本嵌套) 时, 就会先执行子脚本的内容, 完成后再返回父脚本继续执行父脚本内后续的命令及语句.
通常情况下, 在执行 shell 脚本时, 会向系统内核请求启动一个新的进程, 以便在该进程中执行脚本的命令及子 shell 脚本.
基本流程如图所示:
PATH=/root/shell_scripts:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
注意第 1 个路径是我后来加的, 为了执行方便
- [[email protected] ~]# env
- XDG_SESSION_ID=1
- HOSTNAME=centos733.huawei.com
- SELINUX_ROLE_REQUESTED=
- TERM=xterm
- SHELL=/bin/bash
- HISTSIZE=1000
- SSH_CLIENT=192.168.137.34 58583 22
- SELINUX_USE_CURRENT_RANGE=
- SSH_TTY=/dev/pts/0
- USER=root
- LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.PNG=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:
- MAIL=/var/spool/mail/root
- PATH=/root/shell_scripts:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
- PWD=/root
- LANG=en_US.UTF-8
- SELINUX_LEVEL_REQUESTED=
- HISTCONTROL=ignoredups
- SHLVL=1
- HOME=/root
- LOGNAME=root
- SSH_CONNECTION=192.168.137.34 58583 192.168.137.73 22
- LESSOPEN=||/usr/bin/lesspipe.sh %s
- XDG_RUNTIME_DIR=/run/user/0
- _=/usr/bin/env
4 创建 shell 脚本的步骤
第一步: 使用文本编辑器, 比如常见的 VIM 来创建文本文件.
第一行必须包括 shell 声明序列 #!/bin/bash
添加注释, 注释以 #开头
第二步: 运行脚本, 给予执行权限, 在命令行上指定脚本的绝对或相对路径. 直接运行解释器, 将脚本作为解释器程序的参数运行.
由于系统默认的是使用 bash, 所以可以省略不写, 但是把脚本拷到其他的机器上, 不一定使用的是这个 bash. 为了避免产生 BUG 建议都要写.
为了让程序更易于维护, 要加注释, 包括作者, 版本号, 功能等等.
注意 shell 本身是开源的, 没法加密的.
5shell 脚本规范
脚本代码开头约定
1, 第一行一般为调用使用的语言
2, 程序名, 避免更改文件名为无法找到正确的文件
3, 版本号
4, 更改后时间
5, 作者相关信息
6, 该程序的作用, 及注意事项
7, 最后是各版本的更新简要说明
6shell 脚本的基本结构
第一行 #!SHEBANG
变量 CONFIGURATION VARIABLES
函数 FUNCTION DEFINITIONS
主要代码 MAIN CODE
7shell 脚本执行的方式
Shell 脚本的执行通常可以采用以下几种方式
1 bash script-name 或 sh script-name
这是当脚本文件本身没有可执行权限 (即文件权限属性 x 位为 - 号) 时常使用的方法, 或者脚本文件开头没有指定解释器时需要使用的方法.
推荐使用这种方法
2 path/script-name 或 / script-name
在当前路径下执行脚本(脚本需要有执行权限), 需要将脚本文件的权限先改为可执行(即文件权限属性加 x 位),
具体方法为 chmod +x script-name, 然后通过脚本绝对路径或相对路径就可以直接执行脚本了.
在企业生产环境中, 不少运维人员在写完 Shell 脚本之后, 由于忘记为该脚本设置执行权限, 然后就直接应用了, 结果导致脚本没有按照自己的意愿手动或定时执行,
对于这一点, 避免出现该问题的方法就是用第 1 种方法替代第 2 种.
3 source script-name 或. script-name
这种方法通常是使用 source 或 "." (点号)读入或加载指定的 Shell 脚本文件(如 san.sh), 然后, 依次执行指定的 Shell 脚本文件 san.sh 中的所有语句.
这些语句将在当前父 Shell 脚本 father.sh 进程中运行(其他几种模式都会启动新的进程执行子脚本).
因此, 使用 source 或 "." 可以将 san.sh 自身脚本中的变量值或函数等的返回值传递到当前父 Shell 脚本 father.sh 中使用.
这是它和其他几种方法最大的区别.
source 或 "." 命令的功能是: 在当前 Shell 中执行 source 或 "." 加载并执行的相关脚本文件中的命令及语句, 而不是产生一个子 Shell 来执行文件中的命令.
注意 "." 和后面的脚本名之间要有空格.
source 或 "." 相当于 PHP 开发的 include 的功能. HTTP 服务软件 Apache,Nginx 等配置文件里都支持这样的用法.
4 sh<script-name 或 cat scripts-namelsh
同样适用于 bash, 不过不常见
不用循环语句来实现精简开机自启动服务就是通过将所有字符串拼接为命令的形式, 然后经由管道交给 bash 操作
注意不写路径直接执行脚本, 那么就把脚本放到 PATH 变量里面的路径去, 即使是在其他的路径也可以执行.
- [[email protected] shell_scripts]# pwd
- /root/shell_scripts
- [[email protected] shell_scripts]# echo $PATH
- /root/shell_scripts:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
运行第 1 个脚本
注意最后找一个集中的目录来存放自己写的脚本, 便于查看和备份
来源: http://www.bubuko.com/infodetail-3103855.html