Shell命令解释器
| 命令解释器 | |
| bash | 应用最广泛,默认在红帽系列和Debian/Ubuntu使用 |
| dash | Debian/Ubuntu 系统的默认命令解释器 |
| csh、tcsh | 一些unix系统使用 |
| zsh | 功能更强大,支持更多插件,界面美观 |
编程语言分类
解释型(直接解析类):shell、python、php 书写成文件后,可以通过对应的解释器直接运行
编译型(需要编译才能运行):C、C++、Java、Golang 下载好源代码,必须要进行编译生成可以运行的命令
vim优化
# 修改vimrc文件,达到控制vim创建、编辑文件的动作 # 当前用户生效:追加到当前用户目录下 ~/.vimrc # 全局生效:追加到/etc/vimrc set ignorecase autocmd BufNewFile *.py,*.cc,*.sh,*.java exec ":call SetTitle()" func SetTitle() if expand("%:e") == 'sh' call setline(1, "#!/bin/bash") call setline(2, "#########################################") call setline(3, "# File Name: " . expand("%")) call setline(4, "# Version: V1.0") call setline(5, "# Author: yuanxiaojiang") call setline(6, "# Organization: https://www.cnblogs.com/yuanxiaojiang") call setline(7, "# Desc:") call setline(8, "#########################################") endif endfunc
#! 符号含义
用于指定脚本默认的命令解释器
| 命令解释器 | 写法 |
| bash | #!/bin/bash |
| python | #!/usr/bin/python2 或 #!/usr/bin/env python2 |
shell脚本执行方式
| 执行方法 | 应用 |
| 通过sh或bash⭐⭐⭐ | 最常用的执行方式(非红帽系统中,建议使用bash 运行脚本) |
| 通过.(点)或source⭐ |
加载/生效配置文件(环境变量,别名) /etc/profile
常用:可以用来实现include功能,把其他脚本引入到当前脚本中
|
|
通过相对或绝对路径
|
不推荐使用(用于系统脚本/服务调用脚本,脚本需要加上执行权限才能使用) |
|
输入重定向符号
|
不推荐使用
|
sh或bash
[root@m01 ~]# cat /server/scripts/show_info.sh hostname whoami [root@m01 ~]# sh /server/scripts/show_info.sh m01 root
. 或 source
[root@m01 ~]# . /server/scripts/show_info.sh m01 root [root@m01 ~]# source /server/scripts/show_info.sh m01 root
相对或绝对路径
# 给脚本加上执行权限,系统/服务调用某个脚本时使用 [root@m01 ~]# chmod +x /server/scripts/show_info.sh [root@m01 ~]# /server/scripts/show_info.sh m01 root [root@m01 /server/scripts]# ./show_info.sh m01 root
使用重定向符号执行脚本
[root@m01 ~]# sh </server/scripts/show_info.sh m01 root
变量
变量分类
| 分类 | 说明 |
| 普通变量(局部变量) | 在脚本中写的通常是普通变量 |
| 环境变量(全局变量) | 一般有系统创建(PATH、PS1) |
| 特殊变量 | shell编程的核心 |
环境变量
# /etc/profile:用于永久配置用户环境变量和启动程序的脚本文件,主要在用户登录时被执行
# env:用于显示当前的环境变量 # export:用于将一个shell变量标记为环境变量,创建全局变量 # declare:用于声明一个变量并设置其属性 declare MY_VAR="Hello, World!" # 声明普通变量 declare -x MY_ENV_VAR="I am an environment variable" # 声明环境变量 declare -r MY_READONLY="Cannot change me" # 声明只读变量
|
环境变量名字
|
含义
|
应用场景
|
|
PATH
|
记录命令位置的环境变量,运行命令的时候bash会在PATH的路径中查找
|
通过二进制包或编译安装软件,增加新的命令路径
|
|
LANG
|
系统语言与字符集
|
修改语言字符集
|
|
PS1
|
命令行格式
|
修改命令行格式,生产环境不推荐修改
|
|
UID或EUID
|
用户的uid
|
用于判断当前用户是否为root
|
|
HOSTNAME
|
主机名
|
|
|
PROMPT_COMMAND
|
存放命令,命令行执行命令后会运行这个变量的内容,用于实现行为审计(记录用户操作)
|
行为审计 |
|
HISTSIZE
|
内存中保留的历史命令数量 |
未来安全优化配置
|
|
HISTFILESIZE
|
历史记录文件(~/.bash_history)的大小 |
未来安全优化配置
|
|
HISTCONTROL
|
控制如何记录历史命令 |
未来安全优化配置
|
|
HISTFILE
|
指定历史命令记录文件的位置和名称 | 未来安全优化配置 |
|
TMOUT
|
超时自动跳出时间 | 未来安全优化配置 |
环境变量相关文件及其目录
~/.bash_profile:每个用户都可使用该文件输入专用于自己使用的shell信息,当用户登录时,该
文件仅仅执行一次!默认情况下,他设置一些环境变量,执行用户的.bashrc文件.
~/.bashrc:该文件包含专用于你的bash shell的bash信息,当登录时以及每次打开新的shell时,该
该文件被读取.
环境变量文件加载顺序
| 文件或目录 | 作用 | 启动时间 |
| /etc/profile | 系统级配置文件,用于为所有用户设置环境变量和启动程序(该文件通常会调用/etc/profile.d/目录中的所有脚本) | 用户登录到系统时启动 |
| /etc/bashrc | 系统级配置文件,用于设置交互式非登录特性和其他配置(别名、函数的定义) | 打开新的交互式shell |
| ~/.bashrc | 特定用户的配置文件 | 用户打开新的终端窗口或执行新的 Bash shell 时,会读取此文件 |
| ~/.bash_profile | 用户登录时执行的脚本,主要用于设置用户特定的环境变量 | |
| /etc/profile.d | 存放用户自定义或者系统级的脚本 | 登录时执行该目录中的所有脚本 |
登录shell(通过ssh或tty登录)
/etc/profile(/etc/profile.d)
~/.bash_profile
~/.bashrc
/etc/bashrc
案例:书写脚本每次用户登录后显示系统的基本信息
# 未来通过软连接来实现该功能
ln -s /server/scripts/devops_shell/sys_login_info.sh /etc/profile.d/sys_login_info.sh
cat /server/scripts/devops_shell/sys_login_info.sh
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=`w |awk 'NR==1{print $(NF-2) $(NF-1) $NF}'`
# 输出
cat <<EOF
主机名:${sys_hostname}
IP地址:${sys_ip_addrs}
总内存:${sys_mem_total}
可用内存:${sys_mem_free}
系统负载:${sys_load}
EOF
特殊变量
特殊变量-位置变量
| 位置的特殊变量 | 含义 | 应用场景 |
| $n (数字) | 脚本的第n个参数 | 命令行与脚本内部桥梁 |
| $0 | 脚本的名字 | 用于输出脚本的格式或帮助时 |
| $# | 脚本参数的个数 | 一般与判断结合,检查脚本参数个数 |
| $@ $* | 取出脚本所有的参数,$*加上双引号会将所有的参数合并为一个参数 | 数据或循环 |
案例:判断指定的用户是否存在
[root@m01 ~]# cat /server/scripts/devops-shell/check_user.sh if [ $# -ne 1 ];then echo "输入格式正确" exit 1 fi username=$1 if id ${username} &>/dev/null;then echo "用户${username}存在" else echo "用户${username}不存在" fi [root@m01 ~]# sh /server/scripts/devops-shell/check_user.sh root 用户root存在
面试题:$n(n>9)输出结果
$1 = root $10 --> $1+0 --> 取$1的值后面拼接0 root0 $11 --> $1+1 --> 取$1的值后面拼接1 root1
案例:输出脚本所有参数和参数个数
[root@m01 /server/scripts/devops-shell]# cat 01.sh for age in "$@";do echo "$age" done for age in "$*";do # $*加上双引号会将所有的参数合并为一个参数 echo "$age" done echo $# [root@m01 /server/scripts/devops-shell]# sh 01.sh yuan xiao jiang yuan xiao yuan xiao 3
特殊变量-状态变量
| 状态的特殊变量 | 含义 | 应用场景 |
| $? |
上一个命令、脚本的返回值,0表示正确,非0即错误
|
一般与判断检查命令
结果。
|
| $$ |
当前脚本的pid
|
一般写在脚本中获取
脚本pid
|
| $! | 上一个脚本/命令(持续运行)的pid | |
| $_ |
上一个命令的最后一参数,其实下划线是个环境变量,记录了上一个命令、脚本的
最后一个参数. 使用esc+ .(点)
|
特殊变量-变量子串
| 变量子串(parameter表示变量名字) | 含义 |
| ${parameter} | 变量取值 |
| ${#parameter} | 统计变量字符长度 |
| 删除开头、结尾(word表示要删除的内容) | |
| ${parameter#word} |
从变量左边开始删除,按照最短匹配删除
|
| ${parameter##word} |
从变量左边开始删除,按照最长匹配删除
|
| ${parameter%word} |
从变量右边开始删除,按照最短匹配删除
|
| ${parameter%%word} |
从变量右边开始删除,按照最长匹配删除
|
| 截取(切片):类似于cut -c | |
| ${parameter:5} | 从下标为5的字符开始向后截取 |
| ${parameter:5:2} |
从下标为5的字符开始向后截取2个字符
|
| 替换 | |
| ${parameter/word/replace} |
把word替换为replace 仅替换第1个
|
| ${parameter//word/replace} |
把word替换为replace 替换全部
|
[root@m01 ~]# var=yuanxiaoyuan996 [root@m01 ~]# echo ${var#yuan} xiaoyuan996 [root@m01 ~]# echo ${var#*yuan} xiaoyuan996 [root@m01 ~]# echo ${var##*yuan} 996 [root@m01 ~]# echo ${var#*an} xiaoyuan996 # 取出文件名 [root@m01 ~]# echo ${dir##*/} ifcfg-eth0 # 取出路径名 [root@m01 ~]# echo ${dir%/*} /etc/sysconfig/network-scripts [root@m01 ~]# dirname $dir /etc/sysconfig/network-scripts [root@m01 ~]# basename $dir ifcfg-eth0
# 面试题:I am English teacher welcome to English teacher training class.
for循环打印下面这句话中字母数不大于6的单词
[root@m01 /server/scripts/devops-shell]# cat 02.sh
content="I am English teacher welcome to English teacher training class."
content_new=`echo ${content} |sed 's#\.##g'`
for word in $content_new
do
if [ ${#word} -le 6 ];then
echo "单词字符数<=6:${word}"
fi
done
[root@m01 /server/scripts/devops-shell]# sh 02.sh
单词字符数<=6:I
单词字符数<=6:am
单词字符数<=6:to
单词字符数<=6:class
[root@m01 /server/scripts/devops-shell]# echo ${content} |sed 's#\.##g' |xargs -n1 |awk -F"[ ]" 'length($1)<=6'
I
am
to
class
特殊变量-变量扩展(设置默认值)
| 格式 | 含义 |
|
${parameter:-word}
|
变量parameter没定义或为空,把word作为默认值输出,不修改变量内容
|
|
${parameter:=word}
|
变量parameter没定义或为空,把word作为默认值输出,修改变量内容
|
|
${parameter:?word}
|
变量parameter没定义或为空,把word作为默认值输出并输出错误,不修改变量内容
|
|
${parameter:+word}
|
变量parameter没定义或为空,不做任何操作(不输出),否则将变量内容替换成word
|
变量赋值
| 赋值方法 | 格式 | 应用场景 |
| 直接赋值 | var=yuanxiaojiang | 绝大部分场景使用 |
| 命令结果赋值 | hostname=`hostname` | 获取命令的结果:``或$() |
| 脚本传参(通过脚本命令行传参进行赋值) | user_name=$1(脚本的第一个位置参数) | 用于将命令行内容传入脚本 |
| read交互式赋值(读取文件内容赋值给变量) | 通过read命令实现 | 用户交互 |
| -p |
交互的时候提示信息
|
|
| -t |
超过这个时间没有操作,则自动退出
|
|
| -s |
不显示用户的输入.记录密码才用
|
[root@m01 ~]# read -p "请输入密码:" pass 请输入密码:123 [root@m01 ~]# echo $pass 123 # 同时交互赋值 [root@m01 ~]# read -p "请输入两个数字num1 num2:" num1 num2 请输入两个数字num1 num2:1 2 [root@m01 ~]# echo $num1,$num2 1,2
shell编程运算
运算符
| 算数运算符 | + - * / % ^或** | 用于执行基本的数学运算 |
| 关系运算符 |
|
用于比较两个值,返回真或假 |
| 逻辑运算符 |
|
用于逻辑运算,通常与条件判断结合使用 |
| 位运算符 |
|
用于执行位级的操作 |
| 文件测试运算符 |
|
检查文件的属性 |
| 字符串操作运算符 |
|
用于字符串的比较和连接 |
运算方法
| 运算命令/符号 | 说明 | 应用场景 |
| awk | 可以进行计算(带小数),可以与shell脚本进行变量传递 | 一般计算都可以使用awk |
| bc | 用于执行任意精度的算数运算的命令行计算器 | 一般计算都可以使用bc(需要安装) |
| expr |
用于执行简单整数算数运算、字符串操作、逻辑操作的命令
|
一般用于检查输入内容是否位数字 |
| let |
进行计算,整数,变量直接使用即可
|
|
| $(()) |
进行计算,整数,变量直接使用即可
|
|
| $[] |
进行计算,整数,变量直接使用即可
|
awk计算
# 基础用法 [root@m01 ~]# awk 'BEGIN{print 1/3*100}' 33.3333 # 在awk中使用shell变量 awk -v选项用于创建或修改awk中的变量(-v使shell脚本与awk的桥梁) [root@m01 ~]# num=2 [root@m01 ~]# awk -v n1=1 -v n2=$num 'BEGIN{print n1/n2}' 0.5 在awk中变量直接使用即可,不要加上$n1,如果加上了会被awk识别为取列
bc
# -l:显示小数 [root@m01 ~]# echo 5/3 |bc -l 1.66666666666666666666
expr
# expr算数运算符两边需要使用空格 [root@m01 ~]# expr 1+1 1+1 [root@m01 ~]# expr 1 + 1 2 [root@m01 ~]# expr 1 * 1 # *号需要使用转义字符 expr: syntax error [root@m01 ~]# expr 1 \* 1 1
# expr进行计算的结果为0,返回值为一
[root@m01 ~]# expr 1 + 1
2
[root@m01 ~]# echo $?
0
[root@m01 ~]# expr 0 + 0
0
[root@m01 ~]# echo $?
1
案例:对输入的内容检查是否为数字
[root@m01 /server/scripts/devops-shell]# cat 03.sh read -p "请输入任意信息:" str if [ "$str" = "-666" ];then echo "恭喜你触发了隐藏数字" exit 1 fi expr "$str" + 666 &>/dev/null if [ $? -eq 0 ];then echo "${str}是数字" else echo "${str}不是数字" fi
let、$(())、$[]
[root@m01 ~]# n1=666 [root@m01 ~]# n2=999 [root@m01 ~]# let c=n1+n2 [root@m01 ~]# echo $c 1665 [root@m01 ~]# let c++ [root@m01 ~]# echo $c 1666 [root@m01 ~]# echo $((n1+n2)) 1665 [root@m01 ~]# echo $[n1+n2]
浙公网安备 33010602011771号