高级Bash脚本编程入门

简介:

最近在看《Advanced Bash Scripting Guide》这本书,第二章举了一个清除日志的例子,来讲述如何使用Bash进行编程并聊到了一些编程规范。本文主要是基于这部分内容记录我的读书笔记并整理一些相关知识点。

说到清除日志,你可以使用下面命令来完成清除/var/log下的log文件这件事情:

cd /var/log
cat /dev/null > messages 
cat /dev/null > wtmp
echo "Logs cleaned up."

更简单的清除日志方法是:

echo "" >messages 
#或者
>messages 

注意: /var/log/messages 记录系统报错信息 /var/log/wtmp 记录系统登录信息

在Bash编程时,脚本通常都是放到一个文件里面,该文件可以有后缀名也可以没有,例如,你可以将该文件命名为cleanlog,然后在文件头声明一个命令解释器,这里是#!/bin/bash

#!/bin/bash
LOG_DIR=/var/log
cd $LOG_DIR
cat /dev/null > messages
cat /dev/null > wtmp
echo "Logs cleaned up."
exit

当然,还可以使用其他的命令行解释器,例如:

#!/bin/sh
#!/bin/bash
#!/usr/bin/perl 
#!/usr/bin/tcl 
#!/bin/sed -f
#!/usr/awk -f

#自删除脚本
#!/bin/rm

说明:

  • #! 后面的路径必须真实存在,否则运行时会提示Command not found的错误
  • 在UNIX系统中,在!后边需要一个空格。
  • 如果脚本中还包含有其他的#!行,那么bash将会把它看成是一个一般的注释行。

上面代码将/var/log定义为变量,这样会比把代码写死好很多,因为如果你可能想修改为其他目录,只需要修改变量的值就可以。

对于/var/log目录,一般用户没有访问权限,故需要使用root用户来运行上面脚本,另外,用户不一定有修改目录的权限,所以需要增强代码,做一些判断。

#!/bin/bash

LOG_DIR=/var/log
ROOT_UID=0
LINES=50
E_XCD=66
E_NOTROOT=67

# 当然要使用root 用户来运行.
if [ "$UID" -ne "$ROOT_UID" ]
then
    echo "Must be root to run this script."
    exit $E_NOTROOT
fi

cd $LOG_DIR

if[ "$PWD" != "$LOG_DIR" ]
then
    echo "Can't change to $LOG_DIR."
    exit $E_XCD
fi

cat /dev/null > messages
cat /dev/null > wtmp
echo "Logs cleaned up."

#返回0表示成功
exit 0

上面代码一样定义了一些变量,然后加了两个判断,去检查脚本运行中可能出现的错误并打印错误说明。如果脚本运行错误,则程序会退出并返回一个错误码,不同类型的错误对应的错误码不一样,这样便于识别错误原因;如果脚本运行正常,则正常退出,默认返回码为0。

对于cd $LOG_DIR操作判断是否执行成功,更有效的做法是:

#使用或操作替代if else判断
cd /var/log || {
    echo "Cannot change to necessary directory." >&2
    exit $E_XCD
}

通常,我们可能不想全部清除日志,而是保留最后几行日志,这样就需要给脚本传入参数:

#!/bin/bash

LOG_DIR=/var/log
ROOT_UID=0
LINES=50
E_XCD=66
E_NOTROOT=67

# 当然要使用root 用户来运行.
if [ "$UID" -ne "$ROOT_UID" ]
then
    echo "Must be root to run this script."
    exit $E_NOTROOT
fi

cd $LOG_DIR

if[ "$PWD" != "$LOG_DIR" ]
then
    echo "Can't change to $LOG_DIR."
    exit $E_XCD
fi

# 测试是否有命令行参数,非空判断
if [ -n "$1" ]
then
    lines=$1
else
    lines=$LINES # 默认,如果不在命令行中指定
fi

# 保存log file消息的最后部分
tail -$lines messages > mesg.temp
mv mesg.temp messages

cat /dev/null > wtmp
echo "Logs cleaned up."

#返回0表示成功
exit 0

上面使用if else来判断是否有输入参数,一个更好的检测命令行参数的方式是使用正则表达式做判断,以检查输入参数的合法性:

E_WRONGARGS=65 # 非数值参数(错误的参数格式)

case "$1" in
    "" ) lines=50;;
    *[!0-9]*) echo "Usage: `basename $0` file-to-cleanup"; exit $E_WRONGARGS;; 
    * ) lines=$1;;
esac

编写完脚本之后,你可以使用sh scriptname或者bash scriptname来调用这个脚本。不推荐使用sh <scriptname,因为这禁用了脚本从stdin中读数据的功能。更方便的方法是让脚本本身就具有 可执行权限,通过chmod命令可以修改。比如:

chmod 555 scriptname  #允许任何人都具有可读和执行权限

或者:

chmod +rx scriptname #允许任何人都具有可读和执行权限 
chmod u+rx scriptname #只给脚本的所有者可读和执行权限

既然脚本已经具有了可执行权限,现在你可以使用./scriptname来测试这个脚本了。如果这个脚本以一个#!行开头,那么脚本将会调用合适的命令解释器来运行。

这样一个简单的脚本就编写完成并能运行了,从这个例子中,我们可以学到bash编程的一些代码规范:

  • 使用变量
  • 脚本运行中,需要做一些异常判断

除此之外,google公司还定义了一份Shell Style Guide,可以仔细阅读并约束自己去遵循这些规范。

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
6月前
|
监控 Shell Linux
使用Python和Bash编写内网监控工具:自动巡检脚本示例
为了确保内网的顺畅运行,自动化监控工具变得不可或缺。本文将介绍如何使用Python和Bash编写一个简单而强大的内网监控工具,它可以帮助您自动巡检网络和系统状态,及时发现问题并采取措施。
245 0
|
8月前
|
Shell
使用Bash备份脚本
使用Bash备份脚本
54 1
|
10月前
|
运维 Shell
善用chatGPT学习 | bash脚本如何判断字符串在数组中
善用chatGPT学习 | bash脚本如何判断字符串在数组中
147 0
|
11月前
|
安全 Shell 开发工具
记一次符合Google Coding Style的Bash脚本重构
记一次符合Google Coding Style的Bash脚本重构。最近我在思考这样一个问题,顺便看一下gpt对这个问题的解释。搜索发现:
记一次符合Google Coding Style的Bash脚本重构
|
11月前
|
Shell Linux 程序员
Shell-/bin/bash和/bin/sh解释器的误用引起的脚本语法错误
Shell-/bin/bash和/bin/sh解释器的误用引起的脚本语法错误
282 0
|
Ubuntu Shell Linux
Shell脚本的常用执行方式、bash 和 sh 的关系、子shell、Centos 默认的解析器是 bash、Linux 提供的 Shell 解析器、Shell 概述、Shell 脚本入门
采用 bash 或 sh+脚本的相对路径或绝对路径(不用赋予脚本+x 权限)、采用输入脚本的绝对路径或相对路径执行脚本(必须具有可执行权限+x)、在脚本的路径前加上“.”或者 source(了解)原因: 前两种方式都是在当前 shell 中打开一个子 shell 来执行脚本内容,当脚本内容结束,则 子 shell 关闭,回到父 shell 中。第三种,也就是使用在脚本路径前加“.”或者 source 的方式,`可以使脚本内容在当前 shell 里执行,而无需打开子 shell!`这也是为什么我们每次要修改完
568 1
Shell脚本的常用执行方式、bash 和 sh 的关系、子shell、Centos 默认的解析器是 bash、Linux 提供的 Shell 解析器、Shell 概述、Shell 脚本入门
|
11月前
|
JavaScript 前端开发 Shell
别再用 bash 写前端自动化脚本了!
Vladimir[1] 发现自己一直讨厌 bash 编写的自动化流程脚本,并且在机缘巧合下发现同事们都有类似的想法,因此他分享了他认为 JavaScript 编写自动化脚本的优势,看看能不能说服大家去共建更好的生态。
|
11月前
|
Unix Shell Linux
关于 Bash 脚本中 Shebang 的趣事
关于 Bash 脚本中 Shebang 的趣事
|
移动开发 Unix Shell
shell脚本 解决“/bin/bash^M: bad interpreter: No such file or directory”
shell脚本 解决“/bin/bash^M: bad interpreter: No such file or directory”
94 0
|
Ubuntu Shell Linux
Shell脚本的常用执行方式、bash 和 sh 的关系、子shell、Centos 默认的解析器是 bash、Linux 提供的 Shell 解析器、Shell 概述、Shell 脚本入门
Shell脚本的常用执行方式、bash 和 sh 的关系、子shell、Centos 默认的解析器是 bash、Linux 提供的 Shell 解析器、Shell 概述、Shell 脚本入门
Shell脚本的常用执行方式、bash 和 sh 的关系、子shell、Centos 默认的解析器是 bash、Linux 提供的 Shell 解析器、Shell 概述、Shell 脚本入门