做为一名有理想的程序员,咱们或多或少都会写一些 shell
脚本,它们可能很短,只有简单的几个命令,也可能很是长,包含了系统检查、编译和运行等多个庞大复杂的任务java
在安装软件的时候,你必定见过不少名为configure
的 shell
脚本,这个脚本能够保证软件不会破坏当前系统,而且拥有能够正常安装的环境配置,实现这个脚本须要不少的逻辑和技巧。做为一名使用了多年 shell
脚本的老司机,我积累了大量关于 shell
脚本的使用技巧来提升脚本编写效率,今天,我将其中的一些精华分享出来,但愿能对一些人有所帮助linux
刚开始的时候,个人脚本就是一系列的命令,像流水帐同样,通常用来节省写多个标准 shell
语句的时间。好比发布一个 web
网站,其中一个任务就是把静态文件解压到 nginx
目录,脚本大概长这样nginx
$ cp static_file.tar.gz /usr/nginx/home/
$ cd /usr/nginx/home/
$ tar -zxvf static_file.tar.gz
复制代码
这个脚本固然节省了不少的时间,但从长远来看,这并非一个颇有用的脚本。过了一段时间,我学会了一些其余的方式来写脚本,并用来完成更有挑战性的任务,好比建立一个软件包,安装软件或者备份一个文件服务器等程序员
就像其余的变成语言同样,条件判断是一个易用且强大的语法。条件语句可让咱们的程序按照必定的逻辑执行。个人每一个脚本几乎都用到了条件语句web
最基本的条件语句使用 if
标记。if
语句能够对一些条件进行判断,咱们能够根据判断的结果来决定脚本的走向。例如,咱们能够检查 java bin
目录是否存在,若是存在,就表明 java
已经正常安装,而后咱们能够利用脚本,将 java
的运行目录放到 path
环境变量中,这样咱们就能够在任意一个文件目录下运行 java
命令了shell
if [ -d "$JAVA_HOME/bin" ] ; then
PATH="$JAVA_HOME/bin;$PATH"
fi
复制代码
if
条件判断还有一些高级的用法,好比我想判断一个目录是否存在,不存在则建立bash
[ -d "$1" ] || mkdir --parent "$1"
复制代码
也许咱们会想让脚本只能由特定的用户执行。尽管 linux
已经有了用户和组的权限控制,但仍是想让脚原本控制。好比可使用脚原本控制只能是当前 web
容器的全部者才能执行,或者只有 root
用户才能执行。linux
系统给咱们提供了两个环境变量去实现这个功能,其中一个是 $USER
,获取当前用户名。另外一个是 $UID
获取当前用户的惟一标记服务器
在一个多用户,多应用的环境中,下面的示例展现了如何限制,只有 apple
这个用户才能够执行这个脚本。 if
语句能够理解为向用户提问:"执行的用户是否是 不是apple ?"。 若是发现执行人就是 apple
,第一个 echo
就会被执行,后边紧跟着一个 exit 1
,意味着结束脚本执行app
if [ "$USER" != 'apple' ] ; then
echo "此脚本只能由 apple 执行"
exit 1
fi
echo "继续执行脚本"
复制代码
第二个例子展现了,只有 root
用户才能执行此脚本。由于 UID
为 0
的就是 root
用户,咱们能够在判断时使用 -gt
扩展选项来禁止全部 UID
大于 0
的用户继续执行脚本学习
if [ "$UID" -gt 0 ] ; then
echo "此脚本只能由 root执行"
exit 1
fi
echo "继续执行脚本"
复制代码
和任何能够执行的文件同样,脚本文件也能够接受参数。下边会展现一些参数传递的例子。但必定要注意,要写好代码,不只要让程序执行咱们想要执行的任务,也要保证程序不要执行咱们不想执行的任务。我通常在脚本中会确保在用户没有参数传递进来的时候不作任何事情。所以,我写脚本的第一件事就是使用 $#
检查脚本的参数是否传递
if [ $# -eq 0 ] ; then
echo "参数错误"
exit 1
fi
echo "得到了参数: $#"
复制代码
能够在命令行中传递多个参数给脚本, 脚本中对于用户提供的变量提供了很简单的获取方式,以 $
符号开头,按照参数递增,例如 $1 $2 $3
等。 下边的例子是打印用户输入的三个参数。固然,咱们还必需要注意根据参数传递的数量作不一样的处理。
echo $1 $2 $3
复制代码
看了上面的代码,你也许会问:是否是跳过了 $0
?
嗯。。。是的,由于 $0
在脚本中也是一个很是有用的变量,他表明咱们执行的脚本的名称
echo $0
复制代码
对于这个参数的一个很是重要的应用就是在脚本中生成一个包含脚本名称的日志。最简单的例子大概以下
echo test >> $0.log
复制代码
上边只是最简单使用,通常在使用时须要加上一些逻辑判断,好比判断文件位置是否可写等
另一个很是有用的功能就是在脚本执行的时候让用户输入一些信息,以下
echo "请输入一个字母: "
read word
echo $word
复制代码
这样就可让用户在执行脚本的时候进行判断
read -p "是否安装此软件? [Y/n]: " answ
if [ "$answ" == ’n' ] ; then exit 1 fi echo "开始安装软件" 复制代码
几年以前,我写了一个脚本去安装最新版本的 jdk
,这个脚本的基本流程就是解压 jdk
包到指定的目录,更新 jdk
的软链,而后使用一些其余的方式让系统识别这个新版本。这就须要考虑一个问题,若是我解压 jdk
包失败了,继续执行脚本就会破坏我以前安装的 jdk
环境。因此个人脚本必定要能解决这种问题,也就是说只有解压成功才继续执行脚本,大概的源码以下
tar kxzmf jdk-8-linux-x64.tar.gz -C /home/apple/jdk --checkpoint=.500; ec=$?
if [$ec -ne 0 ] ; then
echo "安装 jdk 失败"
exit 1
fi
复制代码
识别系统命令执行出错最简单的方法时使用 $?
变量,以下例
ls T; ec=$?; echo $ec
复制代码
咱们若是先执行 touch T
而后执行上边的脚本,ec
会是 0
。而后删除 T
文件,调用 rm T
。再次执行脚本,ec
会变成 2
,由于 T
文件没有找到,系统会抛出一个为 2
的错误标记
在一些稍微复杂写的场景,咱们可能就会想要用一些比较高级的语言实现,相似 Python
C
或者 Java
。其实很时候彻底没有必要。shell
脚本很是强大,有不少值得学习和使用的东西。我但愿经过上边的简单介绍能让刚刚使用 shell
并准备放弃的人了解到 一点 shell
的强大及魅力