Shell 脚本的心得

简介: 我们经常看到别人写的脚本中第一行会写一个set,这个set是什么意思呢?

set 在脚本中的意义

我们经常看到别人写的脚本中第一行会写一个set,这个set是什么意思呢?

set -o nounset

set -o errexit

set -euo pipefail

....

这都是什么意思呢?

这些set命令都是为了完善shell脚本的逻辑严谨性。

1、在高级语言中如果一个变量未定义会报错,在shell中则不会报错。如何避免这个问题呢?

set -o nounset 或者set -u

‘-u’: 遇到未定义的变量,报错并立即退出。

2、还有一种情况,当使用shell 退出码做判断的时候,如果遇到如下情况

退出码竟然是0. 显然awk语法有问题,如何让这个命令的退出码变为非0呢?

使用-o pipefail

再看这个完成的例子:

$ cat try_bash_o.sh 
#!/bin/bash
set -e -o pipefail
# 'foo' is a non-existing command
foo | echo "a"
echo "bar"
$ ./try_bash_o.sh 
a
./try_bash_o.sh: line 5: foo: command not found
$ echo $?
127
$ sed -i 's/-o pipefail//' try_bash_o.sh 
$ ./try_bash_o.sh 
a
./try_bash_o.sh: line 5: foo: command not found
bar
$ echo $?
0

有时候 这会产生意料之外的错误。

某天IT同事问我,根目录下为何有很多压缩文件,每天一个。

经过一番排查发现这里面的内容竟然是一样的,都是根目录下的*.log文件。每天0点定时生成压缩文件。第一时间想到了crontab

果然发现了下面这个脚本。

f425670561fb408aac5b13f91103adbf.jpg由于cd的目录不存在,则直接变成了根目录,所以才会出现上面的情况。

3、当一个命令失败时,立即退出,如果你不想立即退出则可用‘|| true’

使用-e参数 或者set -o errexit。

一般我们编写的脚本都是需要用到-e的,如果某一步失败不影响结果应该在脚本逻辑中处理而不是使用|| true

bash 中的算数计算

1、算术扩展 (())

 echo $((3+2))
# 使用变量也可以
a=3
echo $((${a}+2))
5

2、expr

expr 是 coreutils 软件包提供的一个命令,可对表达式进行计算,或者比较大小之类的。

x=3
y=7
# 注意加号左右一定要有空格
expr $x + $y
10

80d61699e7c3444099d8954d45169474.png

3、bc

bc 其实是一种支持任意精度和可交互执行的计算语言。它比上述提到的 expr 要强大的多,尤其是它还支持浮点数运算

bc zsh好像默认不支持,bash4.2 是默认支持的

sqrt() 快速的计算平方根。

 echo "scale=2;7/3"|bc
2.33
echo "7/3"|bc
2
echo "scale=2;sqrt(6)" |bc
2.44
echo "scale=2;sqrt(9)" |bc
3.00

bash调试模式

-v  开启详细模式,用于查看所执行的命令, 例如bash -x,或者在脚本中set -x来开启此模式

-x  进入 xtrace 模式,用于调试执行阶段的变量值。

-u  检查变量是否未定义/绑定

cat add.sh 
#!/bin/bash
five=5
ten=10
total=$((five+tne))
echo $total
bash add.sh
5
bash -u add.sh
add.sh: line 4: tne: unbound variable

let i=0的坑

有如下一段代码,执行之后是什么结果呢?

#!/bin/bash
set -e -u
let i=0
while [ $i -lt 6 ]; do
  echo $i
  ((i++))
done

啥都没输出

调试模式

# bash -x tmp.sh
+ set -e -u
+ let i=0

其实这里有一个坑,就是let的返回值,0被认为是不可计算的值,所以状态码返回1

触发了set -e 就直接return了。

看看官方这说法

let arg [arg ...]
              Each arg is an arithmetic expression to be evaluated (see ARITHMETIC EVALUATION above).  If the last arg evaluates to 0, let returns 1; 0 is returned otherwise.
目录
相关文章
|
6天前
|
Shell
一个用于添加/删除定时任务的shell脚本
一个用于添加/删除定时任务的shell脚本
30 1
|
26天前
|
监控 Unix Shell
shell脚本编程学习
【10月更文挑战第1天】shell脚本编程
52 12
|
21天前
|
存储 运维 监控
自动化运维:使用Shell脚本简化日常任务
【9月更文挑战第35天】在IT运维的日常工作中,重复性的任务往往消耗大量的时间。本文将介绍如何通过编写简单的Shell脚本来自动化这些日常任务,从而提升效率。我们将一起探索Shell脚本的基础语法,并通过实际案例展示如何应用这些知识来创建有用的自动化工具。无论你是新手还是有一定经验的运维人员,这篇文章都会为你提供新的视角和技巧,让你的工作更加轻松。
24 2
|
29天前
|
Shell
shell脚本变量 $name ${name}啥区别
shell脚本变量 $name ${name}啥区别
|
1月前
|
人工智能 监控 Shell
常用的 55 个 Linux Shell 脚本(包括基础案例、文件操作、实用工具、图形化、sed、gawk)
这篇文章提供了55个常用的Linux Shell脚本实例,涵盖基础案例、文件操作、实用工具、图形化界面及sed、gawk的使用。
87 2
|
15天前
|
存储 Shell Linux
【Linux】shell基础,shell脚本
Shell脚本是Linux系统管理和自动化任务的重要工具,掌握其基础及进阶用法能显著提升工作效率。从简单的命令序列到复杂的逻辑控制和功能封装,Shell脚本展现了强大的灵活性和实用性。不断实践和探索,将使您更加熟练地运用Shell脚本解决各种实际问题
12 0
|
1月前
|
Shell
Shell脚本有哪些基本语法?
【9月更文挑战第4天】
52 17
|
1月前
|
存储 Unix Shell
shell脚本编程基础
【9月更文挑战第4天】
40 12
|
1月前
|
网络协议 关系型数据库 MySQL
Shell 脚本案例
Shell 脚本案例
41 8
|
1月前
|
Shell Linux 开发工具
linux shell 脚本调试技巧
【9月更文挑战第3天】在Linux中调试shell脚本可采用多种技巧:使用`-x`选项显示每行命令及变量扩展情况;通过`read`或`trap`设置断点;利用`echo`检查变量值,`set`显示所有变量;检查退出状态码 `$?` 进行错误处理;使用`bashdb`等调试工具实现更复杂调试功能。