Shell 脚本是一种用于编写命令序列的脚本语言,这些命令序列可以在 Unix/Linux 系统中执行。Shell 脚本使用 Shell 解释器来执行,常见的 Shell 解释器包括 Bash、sh、csh、zsh 等。Shell 脚本非常适合用于自动化日常任务、处理文件、运行系统任务等。
Shell 脚本的基本结构
一个基本的 Shell 脚本通常包含以下几个部分:
Shebang(#! 行):
这是脚本的第一行,指定了解释脚本的 Shell 解释器。例如,对于 Bash 脚本,第一行应该是 #!/bin/bash。
变量声明:
变量用于存储数据,可以随时修改。变量名通常由字母和下划线组成,且不应以数字开头。
示例:MY_VAR="Hello World"
命令执行:
脚本中可以包含各种命令,如 ls, cd, echo 等。
示例:echo $MY_VAR
控制结构:
Shell 脚本支持各种控制结构,如条件语句 (if, case) 和循环 (for, while)。
示例:
if [ "$USER" = "root" ]; then
echo "You are logged in as root."
else
echo "You are not root."
fi
函数定义:
函数可以让你将一段代码组织在一起,方便重用。
示例:
say_hello() {
echo "Hello, $1"
}
say_hello "Alice"
命令替换:
使用 $() 或者反引号 `command` 来执行命令并将输出结果赋值给变量。
示例:CURRENT_DATE=$(date)
输入输出重定向:
< 用于从文件读取输入。
> 用于将输出写入文件。
>> 用于追加输出到文件。
示例:echo "Hello" > output.txt
示例脚本
下面是一个简单的 Shell 脚本示例,用于打印出当前用户的用户名和系统日期:
#!/bin/bash
# 打印当前用户的用户名
echo "Current user: $USER"
# 获取今天的日期
TODAY=$(date)
# 打印日期
echo "Today's date is: $TODAY"
# 定义一个函数
greet() {
echo "Hello, $1"
}
# 调用函数
greet "$USER"
如何运行 Shell 脚本
保存脚本:
将上面的脚本内容保存到一个文件中,例如命名为 script.sh。
给予执行权限:
在 Linux 或 macOS 上,你可以通过运行 chmod +x script.sh 来给予脚本执行权限。
执行脚本:
直接运行脚本:./script.sh
调试脚本:
使用 -x 选项来开启调试模式,显示脚本执行过程中的每一条命令:
bash -x script.sh
Shell 脚本的一些高级特性
参数处理:
脚本可以接受命令行参数,并通过 $1, $2, ... 来访问。
示例:检查是否传入了参数
if [ -z "$1" ]; then
echo "No argument supplied."
else
echo "Argument supplied: $1"
fi
管道和重定向:
使用 | 符号来连接命令,前一个命令的输出作为后一个命令的输入。
示例:ls | grep "txt" 会列出当前目录下的所有包含 "txt" 的文件名。
环境变量:
Shell 脚本可以访问环境变量,如 PATH, HOME 等。
进程控制:
使用 & 符号来在后台运行命令。
使用 wait 来等待所有后台命令完成。
Shell实现一个日常运维需求
实现以下功能:
- 远程连接到一台或多台机器。
- 删除指定的日志文件。
- 定时启动某个进程。
- 监控内存使用情况。
假设前提
SSH 密钥认证:远程连接使用 SSH 密钥认证,无需密码。
日志文件路径:假设日志文件的路径已知。
启动的进程:需要启动的进程是一个可执行文件,其路径已知。
监控频率:监控内存使用的频率固定。
目标机器列表:目标机器的列表在脚本中定义。
示例脚本
下面是一个示例脚本,包含了上述功能的实现:
#!/bin/bash
# 定义目标机器列表
MACHINES=("user1@192.168.1.100" "user2@192.168.1.101")
# 日志文件路径
LOG_FILE="/var/log/myapp.log"
# 需要启动的进程路径
PROCESS_PATH="/usr/local/bin/myapp"
# 内存监控频率(秒)
MEMORY_MONITOR_INTERVAL=60
# 删除日志文件
delete_logs() {
for machine in "${MACHINES[@]}"; do
echo "Deleting log file on $machine..."
ssh $machine "sudo rm -f $LOG_FILE"
done
}
# 启动进程
start_process() {
for machine in "${MACHINES[@]}"; do
echo "Starting process on $machine..."
ssh $machine "sudo $PROCESS_PATH &"
done
}
# 监控内存使用情况
monitor_memory_usage() {
while true; do
for machine in "${MACHINES[@]}"; do
echo "Checking memory usage on $machine..."
ssh $machine "free -m"
done
sleep $MEMORY_MONITOR_INTERVAL
done
}
# 定时任务
schedule_tasks() {
# 每天凌晨 2 点执行
(crontab -l ; echo "0 2 * * * /path/to/script.sh") | crontab -
}
# 脚本入口
main() {
# 删除日志文件
delete_logs
# 启动进程
start_process
# 设置定时任务
schedule_tasks
# 启动内存监控
monitor_memory_usage &
}
# 运行主函数
main
说明
删除日志文件:
delete_logs 函数遍历目标机器列表,并通过 SSH 连接到每台机器上删除指定的日志文件。
启动进程:
start_process 函数同样遍历机器列表,并通过 SSH 启动指定的进程。这里使用了 & 将进程放到后台运行。
监控内存使用情况:
monitor_memory_usage 函数使用 free -m 命令来监控每台机器的内存使用情况,并按设定的时间间隔运行。
定时任务:
schedule_tasks 函数设置了定时任务,每天凌晨 2 点执行脚本。这需要将脚本的路径替换为实际的路径。
脚本入口:
main 函数是脚本的入口,依次执行删除日志、启动进程、设置定时任务和启动内存监控。
注意事项
确保 SSH 密钥已经配置好,并且从脚本执行的用户账户可以无密码登录到目标机器。
替换脚本中的 MACHINES 列表、LOG_FILE 路径、PROCESS_PATH 路径等变量为实际值。
确认目标机器上的用户有足够的权限执行 sudo 命令。
如果需要更详细的错误处理或日志记录,可以在脚本中添加相应的逻辑。