目录
Shell编程规范与变量 · 前言
Shell脚本作为Linux系统自动化与运维的核心工具,其规范性与变量使用直接影响脚本的健壮性、可维护性及安全性。缺乏命名约定、作用域控制或错误处理易引发隐蔽问题,而变量引号、类型隐式转换及作用域规则等细节,则是编写可靠脚本的关键。掌握规范与变量机制,既能提升代码可读性,也能规避潜在风险,助力高效、安全的脚本开发。
一`shell脚本概述
1.shell的作用
linux系统中的shell是一个特殊的应用程序,它介于系统内核与用户之间,充当一个“命令解释器”的角色 ,负责接收用户的命令并进行解释,传递给内核执行,输出执行结果。
常见的shell解释器可通过/etc/shells文件可以了解当前系统所支持的Shell脚本种类
[root@localhost ~]# cat /etc/shells /bin/sh /bin/bash /usr/bin/sh /usr/bin/bash
2.编写一个新的shell脚本
shell脚本就是将各种linux命令集中保存到一个文件中,然后添加执行权限,这个文件就是一个shell脚本。为了区分文件类型,通常shell文件的后缀名为.sh
vim aaa.sh #创建一个aaa的shell文件 #/bin/bash #这是一个声明,写出使用哪个bash cd /boot/ pwd #查看当前目录 ls -lh * ~
2.1执行shell脚本
执行shell脚本的命令分为两种。一种是在子bash中执行,执行后在当前页面中,另一种在bash中,执行后到/boot下。
[root@localhost ~]# . aaa.sh /boot
3.重定向和管道操作
在 Linux Shell 中,重定向用于控制命令的输入(stdin
)、输出(stdout
)和错误(stderr
)的流向,是脚本编程和系统管理中极为重要的功能。以下是核心用法与场景:
重定向输出:
[root@localhost ~]# uname -p >aaa.txt [root@localhost ~]# cat aaa.txt x86_64
重定向输入:
[root@localhost ~]# vi pass.txt #编辑一个密码为123456的文件 [root@localhost ~]# setenforce 0 #关闭内核机制否则无法执行 [root@localhost ~]# passwd --stdin zhangsan < pass.txt #完成张三用户的密码 更改用户 zhangsan 的密码 。 passwd:所有的身份验证令牌已经成功更新。
错误重定向:
当使用2>输出时,只将错误的信息输出到文件中。使用&>输出时,输出全部内容。
[root@localhost ~]# tar zcf /etc/sss.etc -C /etc/ 2> ccc.txt [root@localhost ~]# cat ccc.txt tar: 谨慎地拒绝创建空归档文件 请用“tar --help”或“tar --usage”获得更多信息。
3.2管道操作
"|"管道符的工作原理:将"|"左边的输出结果作为右边的输入结果,同一命令行可用多个管道。
#这个命令时过滤/etc/passwd文件的以#开头的行和去空格 [root@localhost ~]# grep -v "^#" /etc/passwd | grep -v "^$" /etc/passwd root:x:0:0:Super User:/root:/bin/bash bin:x:1:1:bin:/bin:/usr/sbin/nologin #这个命令是查看内存使用情况时,过滤以/为结尾的行,在过滤第6行 [root@localhost ~]# df -hT |grep "/$" |awk '{print $6}' 1%
二·shell变量的作用·类型
在 Shell 脚本中,变量是存储和管理数据的核心工具,其作用与类型直接影响脚本的灵活性与功能实现。以下是详细说明:
1.使用新变量
[root@localhost ~]# name=zhangsan #添加一个名为name的变量 [root@localhost ~]# echo $name #同过echo命令查看变量 zhangsan [root@localhost ~]# echo {$name}12 #可通过{}符号确定正确的变量名 {zhangsan}12
2.特殊的赋值操作
双引号("")
#但赋值内容中包含空格时,必须以双引号括起来,其他情况忽略。 [root@localhost ~]# name=lisi 111 -bash: 111: 未找到命令 [root@localhost ~]# name="lisi 111" [root@localhost ~]# echo $name lisi 111
单引号('')
#当赋值的内容包含“$,",\等具有特殊符号的字符时,引用单引号,符号内不在引用变量,任何字符都作为普通字符。 [root@localhost ~]# echo $name lisi 111 [root@localhost ~]# sss='ccc $name' [root@localhost ~]# echo $sss ccc $name
反撇号"`
#反撇号`内的命令为可执行,否则出错 [root@localhost ~]# aaa=`ll /etc/passwd` [root@localhost ~]# echo $aaa -rw-r--r--. 1 root root 1170 3月24日 11:51 /etc/passwd #无法使用多个反撇号在同一命令中,可以使用$()代替反撇号。 [root@localhost ~]# eee=$(rpm -qf `which useradd`) [root@localhost ~]# echo $eee shadow-4.14.3-5.oe2403sp1.x86_64
read命令
#read命令是bash内部的命令,通常使用时结合-p选项设置提示信息 [root@localhost ~]# read -p "输入备份路径:" zzz 输入备份路径:/opt/backup [root@localhost ~]# echo $zzz /opt/backup
设置变量的作用范围
默认情况下,新定义的变量只在当前shell环境下有效,称为局部变量。
[root@localhost ~]# pstree systemd─┬─NetworkManager───3*[{NetworkManager}] ├─auditd───{auditd} ├─chronyd ├─crond ├─dbus-daemon ├─firewalld───{firewalld} ├─irqbalance───{irqbalance} ├─login───bash ├─polkitd───3*[{polkitd}] ├─restorecond ├─rngd───3*[{rngd}] ├─rsyslogd───2*[{rsyslogd}] ├─sshd─┬─sshd───sshd───bash───pstree #可查看使用哪个bash环境 │ └─sshd───sshd───sftp-server ├─systemd-journal ├─systemd-logind ├─systemd-udevd └─tuned───3*[{tuned}] #当想要使自定义变量在所有变量中使用,可使用export命令字转化为全局变量 [root@localhost ~]# export name [root@localhost ~]# bash [root@localhost ~]# echo "$name" cccc
数值变量运算
数值运算的基本格式为: 用法:expr 表达式 或:expr 选项
参数1 | 参数2 若 <参数1> 的值不为 0 或 null,则返回 <参数1>, 否则返回 <参数2>
参数1 & 参数2 若两边的值都不为 0 或 null,则返回 <参数1>,否则返回 0
参数1 < 参数2 <参数1> 小于 <参数2> 参数1 <= 参数2 <参数1> 小于或等于 <参数2> 参数1 = 参数2 <参数1> 等于 <参数2> 参数1 != 参数2 <参数1> 不等于 <参数2> 参数1 >= 参数2 <参数1> 大于或等于 <参数2> 参数1 > 参数2 <参数1> 大于 <参数2>
参数1 + 参数2 计算 <参数1> 加 <参数2> 的和 参数1 - 参数2 计算 <参数1> 减 <参数2> 的差
参数1 * 参数2 计算 <参数1> 乘以 <参数2> 的积 参数1 / 参数2 计算 <参数1> 除以 <参数2> 的商 参数1 % 参数2 计算 <参数1> 除以 <参数2> 的余数
实例
[root@localhost ~]# x=2 [root@localhost ~]# y=5 [root@localhost ~]# expr $x \* $y #当使用*法是使用“\"否则将当成文件通配符 10 [root@localhost ~]# expr $x + $y 7 [root@localhost ~]# expr $y / $x 2 [root@localhost ~]# expr $y % $x 1
2.特殊的shell变量
环境变量
环境变量是出于运行而由linux系统提前创建的一类变量,由linux系统自动维护,随着用户状态而变化。
使用env命令可以查看当前工作环境下的环境变量。
[root@localhost ~]# env SHELL=/bin/bash HISTCONTROL=ignoredups HOSTNAME=localhost HISTSIZE=1000 PWD=/root LOGNAME=root MOTD_SHOWN=pam HOME=/root LANG=zh_CN.UTF-8
在Linux系统中,环境变量的全局配置文件为/etc/profile,该文件定义的变量在所有用户中都生效。每个用户都有自己的独立配置文件(~/.bash_profile)。用户可根据自己的需求而更改配置。
vi /etc/profile #进入全局配置文件,添加一个命令,它的作用是将记录的历史命令改为200条 export HISTSIZE=200 #由于上述命令保存后,要下次重启系统才能生效,如果要立即生效,可通过修改环境变量来生效。 [root@localhost boot]# source /root/.bash_profile
只读变量
Shell变量有一种特殊情况,一旦设置,它的值是不能改变的,这种变量叫做只读变量.
#使用readonly命令将变量定义为只读变量,定义后不可在赋值 [root@localhost boot]# name=wangwu [root@localhost boot]# readonly name [root@localhost boot]# echo $name wangwu [root@localhost boot]# name=heliu -bash: name: 只读变量 [root@localhost boot]# unset name -bash: unset: name: 无法取消设定:只读variable [root@localhost boot]# unset ccc
位置变量
位置变量(Positional Parameters)是 Shell 脚本中用于接收命令行参数或函数参数的特殊变量,通过数字和符号直接访问。它们是脚本与用户交互的桥梁,直接影响脚本的灵活性和健壮性。以下是核心内容:
一、基础位置变量
变量 | 含义 | 示例 |
---|---|---|
$0 | 脚本名称或函数名 | ./script.sh |
$1 | 第一个参数 | $1 → 参数1 |
$2 | 第二个参数 | $2 → 参数2 |
... | 依此类推至 ${10} (需加大括号) | ${10} → 第10个参数 |
[root@localhost ~]# vi expr.sh #!/bin/bash SUM=`expr $1 + $2` echo "$1 + $2 = $SUM" [root@localhost ~]# . expr.sh 10 20 10 + 20 = 30
二、预定义变量
变量 | 用途 | 示例 |
---|---|---|
$# | 参数总个数 | $# → 3(若有3个参数) |
$@ | 所有参数列表(每个参数独立) | "$@" → "$1" "$2" "$3" |
$* | 所有参数合并为单个字符串 | "$*" → "$1 $2 $3" |
$? | 上一条命令的退出状态码 | 0 表示成功,非0表示失败 |
$$ | 当前脚本的进程ID(PID) | $$ → 12345 |
$! | 最后一个后台进程的PID | $! → 67890 |
实例:编写一个备份脚本,备份时间戳并打包到指定文件
[root@localhost ~]# vi mybak.sh #!/bin/bash TARFILE=beifen-`date +%s`.tgz tar zcf $TARFILE $* &> /dev/null echo "已执行$0脚本,echo "共完成$#个对象的备份” echo "具体内容为$*" [root@localhost ~]# . mybak.sh /boot/grub 已执行-bash脚本,echo 共完成1个对象的备份” echo 具体内容为/boot/grub [root@localhost ~]# . mybak.sh /etc/passwd /etc/showad 已执行-bash脚本,echo 共完成2个对象的备份” echo 具体内容为/etc/passwd /etc/showad [root@localhost ~]# ls -lh beifen-* -rw-r--r--. 1 root root 45 3月24日 14:08 beifen-1742796503.tgz -rw-r--r--. 1 root root 641 3月24日 14:08 beifen-1742796519.tgz
总结
Shell编程规范与变量的合理使用是编写高效、安全脚本的核心。通过规范命名、严谨的作用域控制、灵活的重定向与管道操作,结合对变量类型和特性的深入理解,可显著提升脚本的健壮性和可维护性。同时,规避常见陷阱并遵循最佳实践,能有效降低运维风险,助力自动化任务的高效执行。