阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

编写快速安全Bash脚本的建议

110次阅读
没有评论

共计 3455 个字符,预计需要花费 9 分钟才能阅读完成。

昨天我和一些朋友聊起 Bash,我意识到:即使我已经使用 Bash 十多年了,现在还有一些基础的杂项,我理解的并不是很清晰。像往常一样,我认为我应该写一个博文。

 编写快速安全 Bash 脚本的建议

我们会包含:

  • 一些 bash 基础知识(“你怎么写一个 for 循环”)
  • 杂项事宜(“总是引用你的 bash 变量”)
  • bash 脚本安全提示(“总是使用 set -u”)

如果你编写 shell 脚本,并且你没有阅读这篇文章中其他任何内容,你应该知道有一个 shell 脚本校验工具(linter),叫做 shellcheck。使用它来使您的 shell 脚本更好!

我们会像讨论编程语言一样讨论 bash,因为,怎么说呢,它就是。这篇文章的目标不是 bash 编程详解。我不会在 bash 中做复杂的编程,也真的不计划学习如何去做。但是,经过今天的思考之后,我认为明确整理下 bash 编程语言的一些基础知识是有用的。bash 编程语言与我使用过的其他编程语言有着很大的不同。

我真的曾认为我已经知道这些东西了,但是通过写这篇文章我依旧学到了一些东西,也许你也会有所收获。

变量赋值

在 bash 中变量赋值按照下面的方式:

VARIABLE=2

并且你可以使用 $VARIABLE(变量名)来引用变量。需要注意的是不要在 = 运算符的两边放置空格符,比如 VARIABLE= 2、VARIABLE = 2、或者 VARIABLE =2,这并不是语法错误,但是将会做完全不需要的事情(比如试图运行一个名字为 2 的程序,并将环境变量 VARIABLE 设置为空字符串)。

Bash 变量并不要求全部大写,但是通常是大写的。

大多数你所使用的 bash 变量都是字符串。在 bash 中也有一些数组变量,但我并不是完全理解它们。

使用 ${}引用变量

有时某些变量,内容为 file.txt,并且我想这样使用它:

mv $MYVAR $MYVAR__bak # wrong!

这段代码是无法工作的!它会去查找 MYVAR__bak 变量,但这并不是一个真实存在的变量。

为了避免类似问题,你需要知道的仅仅是 ${MYVAR}和 $MYVAR 是一回事。所以你可以这样运行指令:

mv $MYVAR ${MYVAR}__bak # right! 全局变量,局部变量和环境变量

Bash 有 3 种变量。我一般先想到(可能也是最常用)的是 环境变量。

Linux 上的每个进程实际上都有环境变量(您可以运行 env 查看当前设置的变量),但在 Bash 中,它们更易于访问。要查看名为 MYVAR 的环境变量,可以运行

echo “$MYVAR”

要设置环境变量,您需要使用 export 关键字:

export MYVAR=2

设置环境变量时,所有子进程将看到该环境变量。所以如果你运行 export MYVAR=2; Python test.py,Python 程序将 MYVAR 设置为 2。

第二种变量是 全局变量。同样像上面那样赋值。

MYVAR=2

在其他编程语言中他们表现得像全局变量。

还有 局部变量,它们的作用域只能存在于 bash 函数中。我基本上从来没有使用过这样的函数(不像我写的其他编程语言),我从来没有使用过局部变量。

for 循环

以下是我在 bash 中编写循环的方法。此循环将从 1 打印到 10。

for i in `seq 1 10` # you can use {1..10} instead of `seq 1 10` do     echo “$i” done

如果你想用一行代码写这个循环,可以这样写:

for i in `seq 1 10`; do echo $i; done

我觉得这是不可能记住的(你要怎么记住在 seq 1 10 之后有一个分号,但是在 do 之后却没有了),所以我不会去记它。

你也可以写 while 循环,但我从来没有这样写过。

有个很酷的事情是你可以遍历另一个命令的输出。seq 1 10 将数字从 1 到 10(每行一个)打印,这个 for 循环只是提取该输出并遍历它。我就经常用这种方法。

您也可以使用反引号或 $()来插入命令的输出。

OUTPUT=`command` # or OUTPUT=$(command)if 语句

在 bash 中的 If 语句是相当让人讨厌去记它。你必须放在这些方括号中,而在方括号之间必须有空格,否则它不起作用。[[和 [ 方括号 (双 / 单) 都工作。这里我们真正进入 bash 的奇怪领域:[是一个程序(/usr/bin/[) 但 [[是 bash 语法。[[ 更好。

if [[“vulture” = “panda”]]; then echo expression evaluated as true else echo expression evaluated as false fi

此外,您可以检查“此文件存在”,“此目录存在”等内容。例如,您可以检查文件 /tmp/awesome.txt 是否存在,如下:

If [[-e /tmp/awesome.txt]]; then  echo “awesome” fi

这通常是有用的,但我必须每次查找语法。

如果您想尝试用命令行,可以使用 test 命令,例如 test -e /tmp/awesome.txt。它成功会返回 0,否则返回错误。

最后一件事是为什么[[比[好:如果你使用[[,那么你可以使用 < 做比较,它不会变成文件重定向。

$ [3 < 4] && echo “true” bash: 4: No such file or directory $ [[3 < 4]] && echo “true” true

还有一个额外的最后一件关于 if 的事:我今天学到是不需要通过[[或者[去使用 if 语句:任何有效的命令都会工作。所以你可以这样做

if grep peanuts food-list.txt then echo “allergy allert!” fi 函数不是那么难

在 bash 中定义和调用函数(特别是没有参数)是非常容易的。

my_function () { echo “This is a function”;} my_function #调用函数总是引用你的变量

另一个 bash 技巧:绝不使用一个没有引用的变量。看看这个看似合理的 shell 脚本:

X=”i am awesome” Y=”i are awesome” if [$X = $Y]; then echo awesome fi

如果你尝试运行这个脚本,你会得到不可理喻的错误消息 script.sh: line 3: [: too many arguments. 什么?

Bash 解释这个 if 语句为 if [i am awesome == i are awesome],这是 6 个字符串 (i, am, awesome, i, are, awesome) 无意义的 if 语句。正确的写法是

X=”i am awesome” Y=”i are awesome” if [“$X” = “$Y”]; then #我放置引号因为我知道 bash 会背叛我,如果我不放的话 echo awesome fi

有些情况下,只要使用 $ X 而不是“$ X”就可以,但是您可以知道何时可以,何时不行吗?我肯定不能。总是引用你的 bash 变量,你会更快乐的。

返回代码, &&, 和 `||

每个 Unix 程序都有一个“返回代码”,它是一个从 0 到 127 的整数。0 表示成功,其他都意味着失败。这在 bash 中是有作用的,因为:有时我从命令行运行一个程序,并希望仅在第一个程序成功的情况下运行第二个程序。

你可以用 && 实现!

例如:create_user && make_home_directory。这将运行 create_user,检查返回代码,然后仅在返回代码为 0 时运行 make_home_directory。

这与 create_user; make_home_directory 不同,无论 create_user 的返回代码是什么,都将运行 make_home_directory。

你也可以使用 create_user || make_home_directory,只有 create_user 运行失败才运行 make_home_directory。这在技术领域中非常巧妙。

后台进程

我不会在此谈及太多关于 job 控制的内容,但是:你可以像下面这样启动后台进程

long_running_command &

如果你后来后悔将进程放到后台,并希望把它带调回前台,你可以用 fg 来做到这一点。如果不止一个进程,您可以使用 jobs 查看所有后台进程。由于某种原因,fg 需要一个“job ID”(这就是 jobs 打印输出的)而不是一个 PID。谁知道 Bash 为什么这样子呢。

另外,如果你在后台运行太多的进程,内置等待命令将等到它们都返回。

说到后悔 – 如果你不小心在错误的终端启动一个进程,Nelson Elhage 有一个很棒的项目叫做 reptyr,可以保存你的进程并将其移到屏幕会话或者某些其他东西中。

扫描二维码,添加马哥个人微信,领取 kindle 大奖!

 编写快速安全 Bash 脚本的建议

正文完
星哥说事-微信公众号
post-qrcode
 
星锅
版权声明:本站原创文章,由 星锅 2022-12-03发表,共计3455字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中