探究 Shell 脚本第一行的作用和写法


前言

在管理一个网站的时候,为了方便 uwsgi 的访问,写了一个脚本:


#!/bin/bash

echo -e "\033[34m---------------------wsgi process--------------------\033[0m" # -e开启转义

ps -ef | grep uwsgi.ini | grep -v grep

sleep 0.5

echo -e "\n--------------------going to close--------------------"

ps -ef | grep uwsgi.ini | grep -v grep | awk '{print $2}' | xargs kill -9 # $2 表示行内的第二个字段,xargs 是传递给命令参数的过滤器

sleep 0.5

echo -e '\n----------check if the kill action is correct----------'

#/pubilc/summer_-python_-project_-backend/uwsgi --ini uwsgi.ini & > /dev/null
uwsgi --ini uwsgi.ini & > /dev/null

echo -e '\n\033[42;1m--------------------started...---------------------\033[0m'

sleep 1

ps -ef | grep uwsgi.ini | grep -v grep

但是在查资料的时候,无意之间发现 shell 脚本开头一行有两种写法,现在探究一下。

这两种写法为 #!/bin/bash#!/usr/bin/env bash

#!/bin/bash 是直接指定了应该去哪里找 bash
#!/usr/bin/env bash 则是告诉系统去 $PATH 包含的目录中挨个去找,先找到哪个,就用哪个。这两种写法各有有缺点,分析如下:

#!/usr/bin/env bash 的优缺点

优点

#!/usr/bin/env bash 不必在系统的特定位置查找命令解释器,为多系统间的移植提供了极大的灵活性和便利性(某些系统的一些命令解释器并不在 /bin 或 一些约定的目录下,而是一些比较奇怪的目录)。
在不了解主机的环境时,#!/usr/bin/env bash 写法可以使开发工作快速地展开。

缺点

#!/usr/bin/env bash 在对安全性比较看重时,该写法会出现安全隐患。

#!/usr/bin/env bash$PATH 中查找命令解释器所在的位置并匹配第一个找到的位置,这意味着可以伪造一个假的命令解释器(如自己写一个bash),并将伪造后的命令解释器所在目录写入 PATH 环境变量中并位于靠前位置,这样,就形成了安全隐患。

/bin 由于一般只有 root 用户才有操作权限,所以,#!/bin/bash 这种写法相对较为安全

#!/usr/bin/env 无法传递多个参数(这是由于 Shebang 解析造成的,并非 env 命令的缘故)。

如:
#!/usr/bin/perl -w
#!/bin/csh -f

而如果使用 #!/usr/bin/env perl -w 这种写法的话,perl -w 会被当成一个参数,于是,根本找不到 perl -w 这个命令解释器,就会出错。

某些系统 env 命令的位置也比较奇怪,这种写法会找不到 env 命令。

#!/bin/bash 的优缺点

优点

准确指出所需命令解释器的位置
安全性相对较高
可以传递多个参数

缺点

移植性相对较差,很多系统的命令解释器位置不一致
一些命令解释器的位置记不住

到底用哪个

两个都可以
如果对安全性比较看重,使用 #!/bin/bash
如果对安全性不是很看重,但对移植性(灵活性)比较看重,使用 #!/usr/bin/env bash,看自己的意愿,喜好

参考博客


Author: Yixiang Zhang
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint policy. If reproduced, please indicate source Yixiang Zhang !
评论
  TOC