在Linux系统中,脚本编程是提升工作效率的核心技能之一,通过将重复性操作封装为可执行的脚本文件,能够实现自动化任务处理、系统管理、批量数据处理等目标,Linux脚本通常使用Shell(如Bash、Zsh等)编写,本文将详细介绍Linux脚本的编写方法,从基础语法到进阶技巧,帮助读者快速上手。
脚本环境准备与基础结构
编写Linux脚本前,需确认系统已安装Shell解释器(默认为Bash,可通过echo $SHELL
查看),脚本文件以.sh
为扩展名(非必须,但便于识别),首行需指定解释器路径,称为Shebang行,格式为#!/bin/bash
(若使用其他解释器,如Zsh则改为#!/bin/zsh
),Shebang行告诉系统使用哪个解释器来执行脚本内容。
创建脚本文件常用命令为touch
或vim
,vim myscript.sh
,进入编辑模式后输入以下基础结构:
#!/bin/bash # 这是一个简单的脚本示例 echo "Hello, Linux Script!"
开头的行是注释,用于解释脚本逻辑,不会被解释器执行;echo
命令用于输出文本到终端。
变量与数据类型
变量定义与引用
Shell变量无需声明类型,直接使用变量名=变量值
定义(等号两侧不能有空格),name="Alice"
、age=25
,引用变量时需在变量名前加或,推荐使用避免歧义(如${name}World
会正确拼接变量与字符串,而$nameWorld
会被视为变量nameWorld
)。
特殊变量
$0
:脚本名称$1-$9
:脚本参数(如./script.sh arg1 arg2
中,$1
为arg1
)- 参数个数
- 所有参数(视为单个字符串)
- 所有参数(视为多个独立字符串)
- 上一条命令的退出状态(0表示成功,非0表示失败)
- 当前进程ID
字符串处理
字符串可通过单引号、双引号或反引号`
包裹,区别如下:
| 引号类型 | 特点 | 示例 | 输出 |
|———-|——|——|——|
| 单引号 | 原样输出,不解析变量和命令 | echo '$name'
| $name
|
| 双引号 | 解析变量和命令 | echo "$name"
| Alice
|
| 反引号 | 执行命令并返回结果 | echo
date“ | 当前日期时间 |
条件判断与流程控制
条件判断:test
或[]
条件判断是脚本逻辑的核心,可通过test
命令或方括号[]
(需与表达式空格隔开)实现,常见判断类型包括:
- 文件判断:
-e
(是否存在)、-f
(是否为普通文件)、-d
(是否为目录)、-r
(是否可读) - 数值比较:
-eq
(等于)、-ne
(不等于)、-gt
(大于)、-lt
(小于) - 字符串判断:(等于)、(不等于)、
-z
(是否为空)
示例:
if [ -f "test.txt" ]; then echo "文件存在" else echo "文件不存在" fi
条件判断逻辑
&&
:逻辑与(前一条命令成功时执行后一条)- 逻辑或(前一条命令失败时执行后一条)
- 逻辑非(取反)
流程控制语句
-
if-else:
if [ $age -ge 18 ]; then echo "成年" elif [ $age -ge 12 ]; then echo "青少年" else echo "儿童" fi
-
for循环:遍历列表或序列
# 遍历列表 for i in "A" "B" "C"; do echo "Item: $i" done # 遍历序列(1到5) for i in {1..5}; do echo "Number: $i" done
-
while循环:条件循环(适合不确定次数的场景)
count=1 while [ $count -le 3 ]; do echo "Count: $count" ((count++)) # 变量自增(等同于count=$count+1) done
-
case语句:多分支匹配
case $1 in "start") echo "启动服务" ;; "stop") echo "停止服务" ;; *) echo "未知参数" ;; esac
函数与参数处理
函数定义与调用
函数将代码块封装为可复用单元,定义方式为:
function myfunc() { echo "函数被调用,参数: $1" } myfunc "Hello" # 调用函数,传入参数
函数通过return
返回状态码(0-255),或通过echo
返回结果(需通过$(函数名)
捕获)。
function add() { echo $(($1 + $2)) } result=$(add 3 5) echo "3+5=$result"
参数处理
脚本可通过位置参数$1
、$2
等接收外部输入,结合shift
命令可处理多个参数(shift
会将参数左移一位,$1
被丢弃,$2
变为$1
),示例:
#!/bin/bash echo "参数个数: $#" for arg in "$@"; do echo "参数: $arg" done
输入输出与重定向
输入输出命令
echo
:输出文本(-n
不换行,-e
解析转义字符如n
)read
:读取用户输入(-p
提示信息,-s
隐藏输入,如密码)read -p "请输入用户名: " username read -s -p "请输入密码: " password echo "用户名: $username"
重定向与管道
>
:覆盖输出(将命令结果写入文件,原内容清空)>>
:追加输出(保留原文件内容,追加到末尾)<
:输入重定向(从文件读取输入)- 管道(将前一条命令的输出作为后一条命令的输入)
示例:
ls -l > file_list.txt # 将文件列表保存到file_list.txt grep "error" log.txt >> error.log # 将log.txt中的error行追加到error.log wc -l < file_list.txt # 统计file_list.txt的行数
调试与执行权限
调试技巧
脚本编写过程中难免出错,可通过以下方式调试:
bash -x script.sh
:以调试模式执行,显示每条命令的执行过程set -x
:在脚本中开启调试(需关闭时用set +x
)echo
输出关键变量值:临时在脚本中添加echo "变量值: $var"
,观察变量是否正确
执行权限
脚本文件需具备执行权限才能通过./script.sh
运行,设置权限命令为:
chmod +x myscript.sh # 添加执行权限 ./myscript.sh # 绝对路径或相对路径执行
若未设置执行权限,也可通过解释器直接执行:bash myscript.sh
。
进阶技巧
数组使用
数组是一组变量的集合,定义方式为:arr=("apple" "banana" "cherry")
,引用元素通过${arr[0]}
(索引从0开始),遍历所有元素用${arr[@]}
或${arr[*]}
。
定时任务
通过crontab
可设置脚本定时执行,
crontab -e # 编辑定时任务 # 添加以下内容表示每天凌晨1点执行脚本 0 1 * * * /path/to/myscript.sh
crontab
格式为:分 时 日 月 周 命令
,表示任意值。
后台运行
脚本默认在前台运行,可通过&
或nohup
在后台执行:
./script.sh &
:后台运行,关闭终端后会终止nohup ./script.sh &
:后台运行且忽略挂断信号,输出默认写入nohup.out
相关问答FAQs
问题1:脚本中如何判断命令是否执行成功?如何处理失败情况?
解答:通过可获取上一条命令的退出状态(0表示成功,非0表示失败),若需判断文件是否存在且可读:
if [ -r "file.txt" ]; then echo "文件可读" else echo "文件不可读或不存在" >&2 # 错误信息输出到标准错误流 exit 1 # 以非0状态码退出脚本 fi
更健壮的方式是结合&&
和实现条件执行:
command1 && command2 # command1成功时执行command2 command1 || command2 # command1失败时执行command2
问题2:如何让脚本在系统重启后自动执行?
解答:可通过/etc/rc.local
或systemd
服务实现。
-
方法1(传统方式):编辑
/etc/rc.local
文件(需确保文件有执行权限),在文件末尾添加脚本路径,/path/to/myscript.sh
注意:某些系统(如Ubuntu 18.04+)需启用
rc-local.service
,可通过systemctl enable rc-local
激活。 -
方法2(推荐,systemd服务):创建服务文件
/etc/systemd/system/myservice.service
如下:[Unit] Description=My Custom Script After=network.target # 网络启动后执行 [Service] Type=oneshot ExecStart=/path/to/myscript.sh User=root Group=root [Install] WantedBy=multi-user.target
保存后执行
systemctl daemon-reload
,systemctl enable myservice
(开机自启),systemctl start myservice
(立即启动)。
原创文章,发布者:酷番叔,转转请注明出处:https://cloud.kd.cn/ask/24809.html