shell编程初识
1. Shell概述,编程语言.
1.1 编程概述
应用广泛: Shell占据的Linux半壁江山.
企业要求:面试要求运维人员必会.
目标:
1.能够熟练书写超过多行的脚本:
检查类:
系统巡检,
系统加固,
优化:(检查,配置优化)
系统优化(初始化)(第2阶段开头).
ngx优化(第2阶段开头).
tomcat优化(第2阶段开头).
数据库优化
安装类(安装,配置,启动)
编译安装nginx
yum安装/apt安装
二进制
...
2. 总计完成书读写5000行脚本(读写).
3. 完成100个脚本书写
SRE运维核心基操:https://www.yuque.com/lidao996/sre/vc088y5l9zof946c?singleDoc#
Shell编程总结:https://www.processon.com/view/link/65653d90c9a10714d94d5a21
1.2 编程语言
1.2.1 编程语言分类
编程语言分类 |
说明 |
解析型:直接解析类 |
shell,python,php, 书写成文件后,可以通过对应的解释器直接运行。 |
编译型:需要编译后运行 |
C,C++,Java(maven),Golang. 下载好源代码,必须要进行编译生成可以运行的命令。 |
1.2.2 Shell编程语言必知必会
Shell命令解释器:bash编程.
常用命令解释器.
命令解释器 |
|
bash |
目前应用最广泛一款命令解释器,红帽系列(默认),Debian,Ubuntu,BASH全称: Bourne-Again SHell |
dash |
一般debian/ubuntu系统默认的, 运行脚本推荐使用 bash 1.sh |
csh,tcsh |
一些unix系统使用 |
zsh |
功能更多,支持更多的插件,可以更好看。 |
⚠shell脚本(.bash .sh),运行在ubuntu中的时候,不推荐使用sh 运行,推荐使用bash运行.
2. Shell环境准备
修改vimrc文件,达到控制vim创建,编辑文件的动作。
当前用户家目录下 ~/.vimrc (只对当前用户生效)
追加:/etc/vimrc (红帽系列) /etc/vim/vimrc(ubuntu debian)
# 1.文件追加如下内容 /etc/vimrc (红帽系列) /etc/vim/vimrc(ubuntu debian)
set ignorecase
autocmd BufNewFile *.py,*.cc,*.sh,*.java,*.bash exec ":call SetTitle()"
func SetTitle()
if expand("%:e") =~ 'sh\|bash\|py'
call setline(1, "#!/bin/bash")
call setline(2,"##############################################################")
call setline(3, "# File Name:".expand("%"))
call setline(4, "# Version:V1.0")
call setline(5, "# Author:xk")
call setline(6, "# Organization: none")
call setline(7, "# Desc:")
call setline(8,"##############################################################")
endif
endfunc
# 2. 使用vim创建sh|bash|py文件
[root@ubuntu2204 /etc/vim]# vim /etc/vim/vimrc
[root@ubuntu2204 ~]# vim 1.sh
[root@ubuntu2204 ~]#
[root@ubuntu2204 ~]# cat 1.sh
#!/bin/bash
##############################################################
# File Name:1.sh
# Version:V1.0
# Author:xk
# Organization: none
# Desc:
##############################################################
[root@ubuntu2204 ~]#
[root@Kylin-V10-sp3 ~]# vim /etc/vimrc
set ignorecase #搜索的时候忽略大小写
配置shell脚本dockerfile docker-compose的vimrc模板
查看代码
#写入到/etc/vimrc文件末尾
autocmd BufNewFile *.py,*.cc,*.sh,*.java,*.bash,Dockerfile,docker-compose.yml exec ":call SetTitle()"
func SetTitle()
if expand("%:e") =~ 'sh\|bash'
call setline(1,"#!/bin/bash")
call setline(2, "##############################################################")
call setline(3, "# File Name: ".expand("%"))
call setline(4, "# Version: V1.0")
call setline(5, "# Author: lidao996")
call setline(6, "# Organization: www.oldboyedu.com")
call setline(7, "# Description:")
call setline(8, "##############################################################")
call setline(9, "")
endif
if expand("%") == 'Dockerfile'
call setline(1, "#####################Dockerfile###############################")
call setline(2, "##############################################################")
call setline(3, "# File Name: ".expand("%"))
call setline(4, "# Version: V1.0")
call setline(5, "# Author: lidao996")
call setline(6, "# Organization: www.oldboyedu.com")
call setline(7, "# Description:")
call setline(8, "##############################################################")
call setline(9, "")
call setline(10, "FROM")
call setline(11, "LABEL maintaniner='oldboy lidao@oldboyedu.com' author=lidao996")
call setline(12, "CMD []")
endif
if expand("%") == 'docker-compose.yml'
call setline(1, "#####################docker-compose###########################")
call setline(2, "##############################################################")
call setline(3, "# File Name: ".expand("%"))
call setline(4, "# Version: V1.0")
call setline(5, "# Author: lidao996")
call setline(6, "# Organization: www.oldboyedu.com")
call setline(7, "# Description:")
call setline(8, "##############################################################")
call setline(9, "")
call setline(10, "version: '3.3'")
call setline(11, "services:")
call setline(12, "volumes:")
endif
endfunc
3. Shell脚本执行方式
3.1 #! 符号含义
sha-bang
并非注释的意思,写在脚本开头.
用于指定脚本默认的命令解释器.
命令解释器 | 写法 |
bash | #!/bin/bash |
python | #!/usr/bin/python2 或 #!/usr/bin/env python2 |
3.2 概述
执行方法 |
应用场景与说明 |
通过sh或bash🌟🌟🌟🌟🌟 |
书写脚本后,最常用的方式, 🌟 ⚠ 在其他非红帽系统中,建议使用bash 运行脚本 . |
通过.(点)或source 🌟 |
🅰 加载/生效配置文件(环境变量,别名) /etc/profile 🅱 常用:可以用来实现include功能,把其他脚本引入到当天脚本中 |
通过相对或绝对路径 |
我们一般不推荐使用这种,一般都是系统脚本/服调用的脚本,脚本需要加上执行权限才能用 |
输入重定向符号 |
不推荐使用. |
在Linux中,.(点命令)、bash和source的区别
# 在Linux中,.(点命令)、bash和source命令在执行脚本时有着明显的区别,主要体现在执行环境、脚本权限要求以及对当前shell环境的影响上。
1. 执行环境
.(点命令)和source命令:它们都是在当前shell环境下执行脚本,这意味着脚本中定义的变量、函数等环境变化会直接反映在当前shell会话中。
由于不需要新启动一个子shell,这些命令执行效率也相对较高。实际上,.命令是source命令的另一种表示方式,两者在功能上是等价的。
bash命令:当使用bash script.sh这种方式执行脚本时,会启动一个新的bash子shell来执行脚本中的命令。这个子shell是独立的,
它继承了父shell的环境变量和其他shell特性,但子shell中的变量和函数变化不会影响到父shell。
2. 脚本权限要求
.(点命令)和source命令:执行脚本时,不需要脚本文件具有执行权限。这是因为它们是在当前shell环境下读取并执行脚本内容,而不是直接执行脚本文件。
bash命令:当直接使用bash script.sh时,如果脚本文件没有执行权限,通常会因为权限不足而报错。但在某些情况下,如果bash能够直接读取脚本文件
的内容(比如通过管道或重定向),则即使脚本没有执行权限也能被执行。然而,直接通过文件名调用bash执行脚本时,脚本文件通常需要具有执行权限。
3. 对当前shell环境的影响
.(点命令)和source命令:由于它们在当前shell环境下执行脚本,因此脚本中定义的变量、函数等环境变化会直接影响到当前shell会话。
这对于需要重新加载配置文件(如.bashrc、.bash_profile等)或临时改变shell环境变量的场景非常有用。
bash命令:由于在新的子shell中执行脚本,脚本中的环境变化不会影响到父shell。这意味着脚本执行完毕后,父shell的环境变量、函数等状态将保持不变。
# 总结
.(点命令)和source命令适用于需要在当前shell环境下执行脚本并修改当前shell环境的场景。
bash命令适用于需要在独立的子shell中执行脚本的场景,或者当脚本文件需要执行权限时。
3.2.1 sh或bash
# Kylin-V10-sp3 sh是bash的软链接
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# ll /bin/ | egrep -w ^'sh|bash'
-rwxr-xr-x 1 root root 1162856 8月 26 2022 bash
lrwxrwxrwx 1 root root 4 8月 26 2022 sh -> bash
[root@Kylin-V10-sp3 /server/scripts/shell-pro]#
# centos7 sh是bash的软链接
[root@centos7 ~]# ll /bin/ | egrep -w ^'sh|bash'
-rwxr-xr-x. 1 root root 964536 Apr 1 2020 bash
lrwxrwxrwx. 1 root root 4 Aug 17 13:48 sh -> bash
[root@centos7 ~]#
# ubuntu2204 sh是dash的软连接
[root@ubuntu2204 /bin]# ll /bin/ | egrep -w '(bash|sh)'
-rwxr-xr-x 1 root root 1396520 Mar 14 2024 bash*
-rwxr-xr-x 1 root root 5188 Mar 25 2022 gettext.sh*
lrwxrwxrwx 1 root root 4 Mar 14 2024 rbash -> bash*
-rwxr-xr-x 1 root root 38964 Mar 22 2023 rescan-scsi-bus.sh*
lrwxrwxrwx 1 root root 4 Mar 23 2022 sh -> dash*
lrwxrwxrwx 1 root root 7 Aug 13 21:39 static-sh -> busybox*
[root@ubuntu2204 /bin]#
# 综上所述shell脚本里 /bin/bash 通用
3.2.2 .或source
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# cat test.sh
#!/bin/bash
##############################################################
# File Name:test.sh
# Version:V1.0
# Author:xk
# Organization: none
# Desc:
##############################################################
echo $a
[root@Kylin-V10-sp3 /server/scripts/shell-pro]#
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# a=123
[root@Kylin-V10-sp3 /server/scripts/shell-pro]#
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# bash test.sh
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# sh test.sh
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# . test.sh
123
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# source test.sh
123
[root@Kylin-V10-sp3 /server/scripts/shell-pro]#
# 原因参考上面 在Linux中,.(点命令)、bash和source的区别
3.2.3 相对或绝对路径
# 脚本中推荐使用绝对路径
3.2.4 使用重定向符号执行脚本
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# cat test.sh
#!/bin/bash
##############################################################
# File Name:test.sh
# Version:V1.0
# Author:xk
# Organization: none
# Desc:
##############################################################
echo $a
echo 123
[root@Kylin-V10-sp3 /server/scripts/shell-pro]#
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# sh < test.sh
123
[root@Kylin-V10-sp3 /server/scripts/shell-pro]#
4. 变量
4.1 变量
变量variable 变化。
小学题:已知 x=30,x+y=20 ,问y=?,y叫未知数.
查看变量内容$变量名字
赋值a = 123
变量的本质:内存中的一块空间,变量名字==>内存空间地址.
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# a=123
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# echo $a
123
[root@Kylin-V10-sp3 /server/scripts/shell-pro]
4.2 变量命名
变量名字命名要求:
- 不能以数字开头。
- 不能以特殊符号开头,可以以"_"开头。
- 推荐字母开头
变量的命名方式:
- 驼峰方式: personOfName personOfAge
- 现代式: 单词(小写)+ "_下划线"连接 person_of_name
- 不要写不能直接表示含义的变量.
4.3 变量分类
分类 |
说明 |
要求 |
普通变量 (局部变量) |
我们在脚本中通过 a=形式创建就是普通变量 |
常用,必会 |
环境变量(全局变量) |
一般都是系统创建,PATH,PS1,LANG... |
掌握几个常用的环境变量及含义 |
特殊变量⭐ ⭐ ⭐ |
$+特殊符号, shell脚本,命令,各种方面. |
shell编程核心 |
4.3.1 普通变量
$与${}一致,可以用于取值。
$变量
${变量} 指定变量名字
day=6
echo $day
6
echo ${day}hao
6hao
4.3.2 环境变量
全局变量: 1处定义,处处使用.
大部分都是系统定义的,我们一般就是修改.
[root@Kylin-V10-sp3 ~]# export
declare -x DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/0/bus"
declare -x HISTCONTROL="ignoredups"
declare -x HISTSIZE="1000"
declare -x HOME="/root"
declare -x HOSTNAME="Kylin-V10-sp3"
declare -x LANG="zh_CN.UTF-8"
declare -x LOGNAME="root"
declare -x LS_COLORS="rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:"
declare -x MAIL="/var/spool/mail/root"
declare -x MOTD_SHOWN="pam"
declare -x OLDPWD
declare -x PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/bin"
declare -x PS1="[\\[\\e[34;1m\\]\\u@\\[\\e[0m\\]\\[\\e[32;1m\\]\\H\\[\\e[0m\\]\\[\\e[31;1m\\] \\w\\[\\e[0m\\]]\\\$ "
declare -x PWD="/root"
declare -x SHELL="/bin/bash"
declare -x SHLVL="1"
declare -x SSH_CLIENT="10.0.0.1 61241 22"
declare -x SSH_CONNECTION="10.0.0.1 61241 10.0.0.36 22"
declare -x SSH_TTY="/dev/pts/0"
declare -x TERM="xterm"
declare -x USER="root"
declare -x XDG_RUNTIME_DIR="/run/user/0"
declare -x XDG_SESSION_CLASS="user"
declare -x XDG_SESSION_ID="6"
declare -x XDG_SESSION_TYPE="tty"
[root@Kylin-V10-sp3 ~]#
[root@Kylin-V10-sp3 ~]#
[root@Kylin-V10-sp3 ~]# env
SHELL=/bin/bash
HISTCONTROL=ignoredups
HISTSIZE=1000
HOSTNAME=Kylin-V10-sp3
PWD=/root
LOGNAME=root
XDG_SESSION_TYPE=tty
MOTD_SHOWN=pam
HOME=/root
LANG=zh_CN.UTF-8
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:
SSH_CONNECTION=10.0.0.1 61241 10.0.0.36 22
XDG_SESSION_CLASS=user
TERM=xterm
USER=root
SHLVL=1
XDG_SESSION_ID=6
XDG_RUNTIME_DIR=/run/user/0
PS1=[\[\e[34;1m\]\u@\[\e[0m\]\[\e[32;1m\]\H\[\e[0m\]\[\e[31;1m\] \w\[\e[0m\]]\$
SSH_CLIENT=10.0.0.1 61241 22
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/bin
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/0/bus
MAIL=/var/spool/mail/root
SSH_TTY=/dev/pts/0
_=/usr/bin/env
[root@Kylin-V10-sp3 ~]#
环境变量名字 |
重 要 程 度 |
含义 |
应用场景 |
PATH |
⭐ ⭐ ⭐ ⭐ ⭐ |
记录命令位置的环境变量,运行命令的时候bash会在PATH的路径中查找 |
通过二进制包或编译安装软件,增加新的命令路径 |
LANG |
⭐ ⭐ ⭐ ⭐ ⭐ |
系统语言与字符集Language LANG=zh_CN.UTF8 中文 LANG=en_US.UTF8 英文 |
修改语言字符集 export LANG=en_US.UTF8(常用) |
PS1 |
⭐ ⭐ |
修改命令行格式,生产环境不推荐修改. |
|
UID或EUID |
⭐ ⭐ |
用户的uid,用于判断当前用户是否为root |
用于脚本判断用户是否root. |
HOSTNAME |
⭐ ⭐ |
主机名 |
|
历史四人组 |
history命令 历史命令相关 |
||
HISTSIZE |
⭐ ⭐ |
history 命令记录最多多条指令, 生产环境尽量少 |
未来安全优化配置 |
HISTFILESIZE |
⭐ ⭐ |
history 历史记录文件的大小 ~/.bash_history 生产环境尽量少 |
未来安全优化配置 |
HISTCONTROL |
⭐ ⭐ |
控制历史命令记录或不记录哪些内容 生产环境ignorespace 以空格开头的命令不记录 |
未来安全优化配置 |
HISTFILE |
⭐ ⭐ |
指定历史命令的记录文件的名字和位置. 默认当前用户家目录 .bash_history
|
未来安全优化配置 或 手写跳板机/行为审计 |
PROMPT_COMMAND |
⭐ ⭐ |
存放命令,命令行执行命令后会运行这个变量的内容,用于实现行为审计(记录用户操作) |
手写跳板机/行为审计 |
IFS |
⭐ ⭐ |
类似于awk -F 指定分隔符(指定每一列的分隔符) |
一般与循环配合读取文件内容 |
TMOUT |
⭐ ⭐ |
超时自动退出时间 |
未来安全优化配置 |
修改环境变量
export 创建或修改全局变量(环境变量)
# 案例01 把当前系统语言改为中文,字符集改为UTF-8
export LANG=zh_CN.UTF-8
#永久的就是写入到 /etc/profile最后即可.
source /etc/profile
env |grep LANG
LANG=zh_CN.UTF-8
4.3.3 环境变量相关文件及目录
修改rm别名的时候为何修改/etc/profile后不生效?还需要修改~/.bashrc
文件或目录 |
应用场景 |
|
/etc/profile |
全局生效(国法) 存放函数,环境变量。存放别名 |
未来主要使用这个即可. |
/etc/bashrc |
全局生效(国法) 存放别名。 |
|
~/.bashrc |
家规(局部生效) |
|
~/.bash_profile |
家规(局部生效) |
|
/etc/profile.d/ |
目录,每个用户登录的时候(远程连接与su切换),加载目录下面.sh结尾的文件. |
简单设置一些登录登录后提示,变化. |
4.3.4 特殊变量 ⭐⭐⭐⭐⭐
linux,shell编程中有各种各样的特殊变量,方便对参数,命令结果,进行判断与对比
特殊变量分类 |
核心 |
位置相关的特殊变量 |
⭐⭐⭐⭐⭐ |
状态相关的特殊变量 |
⭐⭐⭐⭐⭐ |
变量子串 |
⭐、 |
变量扩展 |
⭐ |
4.3.4.1 特殊变量-位置变量
位置的特殊变量 |
含义 |
应用场景 |
$n(数字) |
脚本的第n个参数 |
命令行与脚本内部桥梁. |
$0 |
脚本的名字 |
用于输出脚本的格式或帮助的时候。用于错误提示输出帮助。 |
$# |
脚本参数的个数 |
一般与判断结合,检查脚本参数个数。 |
$@ |
取出脚本所有参数(2, 4....$n)。 |
数组中或循环中。 |
$* |
取出脚本所有参数(2, 4....$n)。 |
数组中或循环中。 |
4.3.4.1.1 $n 位置参数
4.3.4.1.2 练习
1.书写脚本每次用户登录后显示系统的基本信息。 ⭐⭐⭐⭐⭐
查看代码
# 1.书写脚本 (推荐存放位置 /server/scripts/shell-pro/)
#!/bin/bash
##############################################################
# File Name:sys_cfg.sh
# Version:V1.0
# Author:xk
# Organization: none
# Desc:
##############################################################
#########
#1.赋值##
#########
sys_hostname=`hostname`
sys_ip_addrs=`hostname -I`
sys_mem_total=`free -h |awk 'NR==2{print $2}'`
sys_mem_free=`free -h |awk 'NR==2{print $NF}'`
sys_load=`uptime |awk '{print $(NF-2),$(NF-1),$NF}'`
#########
#2.输出##
#########
cat <<EOF
主机名: ${sys_hostname}
ip地址: ${sys_ip_addrs}
总内存: ${sys_mem_total}
可用内存: ${sys_mem_free}
系统负载: ${sys_load}
EOF
# 2.创建软链接
[root@Kylin-V10-sp3 /etc/profile.d]# ls
bash_completion.sh colorls.csh colorls.sh csh.local gawk.csh gawk.sh lang.csh lang.sh sh.local system-info.sh
[root@Kylin-V10-sp3 /etc/profile.d]#
[root@Kylin-V10-sp3 /etc/profile.d]# ln -s /server/scripts/shell-pro/sys_cfg.sh /etc/profile.d/sys_cfg.sh
[root@Kylin-V10-sp3 /etc/profile.d]#
[root@Kylin-V10-sp3 /etc/profile.d]# ll
总用量 40
-rw-r--r-- 1 root root 729 3月 6 2021 bash_completion.sh
-rw-r--r-- 1 root root 1741 4月 20 2022 colorls.csh
-rw-r--r-- 1 root root 1606 4月 20 2022 colorls.sh
-rw-r--r-- 1 root root 80 3月 13 2021 csh.local
-rw-r--r-- 1 root root 1107 1月 25 2019 gawk.csh
-rw-r--r-- 1 root root 757 1月 25 2019 gawk.sh
-rw-r--r-- 1 root root 3562 3月 13 2021 lang.csh
-rw-r--r-- 1 root root 3187 3月 13 2021 lang.sh
-rw-r--r-- 1 root root 81 3月 13 2021 sh.local
lrwxrwxrwx 1 root root 36 9月 19 17:44 sys_cfg.sh -> /server/scripts/shell-pro/sys_cfg.sh
-rw-r--r-- 1 root root 1873 3月 24 2023 system-info.sh
[root@Kylin-V10-sp3 /etc/profile.d]#
# 3 断开当前会话窗口,重新链接。
/**
* _ooOoo_
* o8888888o
* 88" . "88
* (| -_- |)
* O\ = /O
* ___/`---'\____
* . ' \\| |// `.
* / \\||| : |||// \
* / _||||| -:- |||||- \
* | | \\\ - /// | |
* | \_| ''\---/'' | |
* \ .-\__ `-` ___/-. /
* ___`. .' /--.--\ `. . __
* ."" '< `.___\_<|>_/___.' >'"".
* | | : `- \`.;`\ _ /`;.`/ - ` : | |
* \ \ `-. \_ __\ /__ _/ .-` / /
* ======`-.____`-.___\_____/___.-`____.-'======
* `=---='
* .............................................
* 佛曰:bug泛滥,我已瘫痪!
*/
===========================================================
Activate the web console with: systemctl enable --now cockpit.socket
Last login: Thu Sep 19 17:39:44 2024 from 10.0.0.1
# 看到如下内容即设置成功
主机名: Kylin-V10-sp3
ip地址: 10.0.0.36
总内存: 948Mi
可用内存: 528Mi
系统负载: 0.00, 0.00, 0.00
[root@Kylin-V10-sp3 ~]#
2.执行脚本的时候输入用户名,判断用户名是否存在
查看代码
#!/bin/bash
##############################################################
# File Name:check_user.sh
# Version:V1.0
# Author:xk
# Organization: none
# Desc:
##############################################################
# 1 定义变量
user=$1
# 2 检查脚本参数个数
if [ $# -ne 1 ];then
echo '脚本使用格式: ' $0 '用户名'
exit 0
fi
id $user > /dev/null 2>&1
# 3 检查用户是否存在
if [ $? -eq 0 ];then
echo '用户' $user '存在'
else
echo '用户' $user '不存在'
fi
# 调用脚本
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# bash check_user.sh
脚本使用格式: check_user.sh 用户名
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# bash check_user.sh xk
用户 xk 不存在
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# bash check_user.sh root
用户 root 存在
[root@Kylin-V10-sp3 /server/scripts/shell-pro]#
# 判断多用户是否存在
# 传进来的所有用户
users="$@"
# 传参为空,提示正确格式
if [ $# -eq 0 ];then
echo "使用格式:" $0 " user1 user2 ..."
exit
fi
# 循环用户
for user in $users;
do
id $user >/dev/null 2>&1
# id 用户名 结果为0,用户存在
if [ $? -eq 0 ];then
echo $user ": 存在"
else
echo $user ": 不存在"
fi
done
# exit退出脚本,结束执行退出脚本.
# exit 数字,脚本的返回值
3. 检查ip或域名是否可以访问脚本
# 1.脚本内容
#!/bin/bash
##############################################################
# File Name:check_ip.sh
# Version:V1.0
# Author:xk
# Organization: none
# Desc:
##############################################################
ip=$1
if [ $# -ne 1 ];then
echo 'ip or DNS 不存在'
exit
fi
ping -nc1 $ip >/dev/null 2>&1
if [ $? -eq 0 ];then
echo $ip "可以访问脚本"
else
echo $ip "不能访问脚本"
fi
# 2.调用
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# bash check_ip.sh 10.0.0.37
10.0.0.37 可以访问脚本
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# bash check_ip.sh
ip or DNS 不存在
4.面试题: $n n大于9 会有什么问题?
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# cat test.sh
#!/bin/bash
##############################################################
# File Name:test.sh
# Version:V1.0
# Author:xk
# Organization: none
# Desc:
##############################################################
# echo $a
echo 脚本传参:$1 ,$2 ,$3 ,$10 , $11 ,$12
echo 脚本传参2:$1 ,$2 ,$3 ,${10} , ${11}, ${12}
echo 脚本名字:$0
echo 传参个数:$#
[root@Kylin-V10-sp3 /server/scripts/shell-pro]#
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# bash test.sh nice beautiful {a..z}
脚本传参:nice ,beautiful ,a ,nice0 , nice1 ,nice2
脚本传参2:nice ,beautiful ,a ,h , i, j
脚本名字:test.sh
传参个数:28
[root@Kylin-V10-sp3 /server/scripts/shell-pro]#
# 脚本传参:nice ,beautiful ,01 ,nice0 , nice1 ,nice2 # nice0 , nice1 ,nice2 异常
# 脚本传参2:nice ,beautiful ,a ,h , i, j # 使用${}的正常了.
5.执行脚本输入1个或多个用户名,通过脚本进行输出.(难)
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# cat check_multi_users.sh
#!/bin/bash
##############################################################
# File Name:check_multi_users.sh
# Version:V1.0
# Author:xk
# Organization: none
# Desc:
##############################################################
# 传进来的所有用户
users="$@"
# 传参为空,提示正确格式
if [ $# -eq 0 ];then
echo "使用格式:" $0 " user1 user2 ..."
exit
fi
# 循环用户
for user in $users;
do
id $user >/dev/null 2>&1
# id 用户名 结果为0,用户存在
if [ $? -eq 0 ];then
echo $user ": 存在"
else
echo $user ": 不存在"
fi
done
# 调用
[root@Kylin-V10-sp3 /server/scripts/shell-pro]#
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# bash check_multi_users.sh
使用格式: check_multi_users.sh user1 user2 ...
[root@Kylin-V10-sp3 /server/scripts/shell-pro]#
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# bash check_multi_users.sh xk root
xk : 存在
root : 存在
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# bash check_multi_users.sh xk xk2
xk : 存在
xk2 : 不存在
[root@Kylin-V10-sp3 /server/scripts/shell-pro]#
6.书写一个回收站脚本,替代rm命令.
思路
# 脚本详细流程:
1.检查脚本参数个数等于0则报错并退出.
2.脚本创建回收站目录mktemp命令创建临时目录
3.把删除的文件或目录移动到这个临时目录中.
4 输出表示已经移动到回收站(临时目录名字)
5. 执行脚本传入参数被删除的文件或目录. bash recycle.sh /root/test
mktemp -dp /recycle/ 在指定目录下面创建随机目录
默认创建随机文件,在/tmp/
-d创建随机目录
-p指定在哪个目录下面创建随机内容
# 后期需求:
追加需求:禁止删除/etc/ /根目录 /tmp/ /usr /var/
较为复杂的需求:书写恢复的功能.(删除的时候记录文件,记录目录路径.)
rm命令如果加上选项-fr -f
书写回收站脚本.
查看代码
# 1.书写脚本
#!/bin/bash
##############################################################
# File Name:recycle.sh
# Version:V1.0
# Author:xk
# Organization: none
# Desc:
##############################################################
# 移动内容
files="$*"
# 移动目录
path="/recycle/"
if [ $# -eq 0 ];then
echo "help:删除内容不存在"
exit
fi
# mkdir -p $path
# 随机创建子目录
tmp_path=`mktemp -d -p $path`
# 移动文件
mv -t ${tmp_path} ${files}
if [ $? -eq 0 ];then
echo "移动成功,移动到:" ${tmp_path}
else
echo "移动失败"
fi
# 2.设置别名
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# alias rm='bash /server/scripts/shell-pro/recycle'
[root@Kylin-V10-sp3 /server/scripts/shell-pro]#
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# vim /etc/profile
[root@Kylin-V10-sp3 /server/scripts/shell-pro]#
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# source /etc/profile
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# tail -n1 /etc/profile
alias rm='bash /server/scripts/shell-pro/recycle.sh'
[root@Kylin-V10-sp3 /server/scripts/shell-pro]#
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# cat /root/.bashrc
# .bashrc
# User specific aliases and functions
#alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
[root@Kylin-V10-sp3 /server/scripts/shell-pro]#
# 3.调用脚本
[root@Kylin-V10-sp3 ~]# cd test/
[root@Kylin-V10-sp3 ~/test]#
[root@Kylin-V10-sp3 ~/test]# rm 01.txt
移动成功,移动到: /recycle/tmp.XEXKWS1lzV
[root@Kylin-V10-sp3 ~/test]#
[root@Kylin-V10-sp3 ~/test]# ls /recycle/tmp.XEXKWS1lzV/
01.txt
[root@Kylin-V10-sp3 ~/test]#
4.3.4.1.3 了解: $* $@
参数个数不确定
$@和$*区别: 仅仅在加上双引号后才有
符 号 |
共同点 |
区别 |
$@ |
取出脚本所有的参数 |
加上双引号 会识别 合并在一起的参数,独立参数,正常的理解. |
$* |
取出脚本所有的参数 |
加上双引号 所有参数合并为1个参数 |
[root@Kylin-V10-sp3 ~/test]# set "I am boy" handsome man
[root@Kylin-V10-sp3 ~/test]#
[root@Kylin-V10-sp3 ~/test]# for i in "$*"; do echo $i; done
I am boy handsome man
[root@Kylin-V10-sp3 ~/test]#
[root@Kylin-V10-sp3 ~/test]# for i in "$@"; do echo $i; done
I am boy
handsome
man
[root@Kylin-V10-sp3 ~/test]#
4.3.4.1.4 特殊变量之位置变量小结
位置的特殊变量 |
重要 |
含义 |
应用场景 |
$n(数字) 命令行传参 |
⭐⭐⭐⭐⭐ |
脚本的第n个参数 |
使用最多,命令行与脚本内部桥梁. (命令行传参) |
$0 |
⭐⭐⭐⭐ |
脚本的名字 |
用于输出脚本的格式或帮助的时候。用于错误提示输出帮助。 |
$# |
⭐ |
脚本参数的个数 |
一般与判断结合,检查脚本参数个数。 |
$@ |
⭐ |
取出脚本所有参数。 |
数组中或循环中。 |
$* |
⭐ |
取出脚本所有参数。 |
数组中或循环中。 |