linux基础指令
基础
查看指令帮助:
指令 --help
man 指令(更全、分页)
ls、ll
clear
pwd
cd
touch
mkdir -p /tmp/a/b/c #创建多级目录
cp:复制
历史指令:
history #查看当前用户所有历史指令。~/.bash_history。注:系统退出后才会保存
!xx #注:从历史指令中找最后一条以xx开头的指令并执行
echo:
echo "abc"
echo $PATH
rm:
-f:force
-r:recursive递归
rm -rf aa*.txt
cat:
cat a.txt
cat -n a.txt #-n显示行号。基本等价于: nl a.txt [nl 指令对于空行不算行号]
nl:查看文本(显示行号)
nl a.txt
head:
head -10 a.txt
tail:
tail -10 a.txt
tail -f a.txt #follow
more:支持分页(下一页:空格、上一页:b)
less:支持分页、搜索
useradd:
useradd xuan
passwd:
passwd xuan
userdel:
userdel xuan
chmod:
chmod u+rwx 1.txt
#注:u表示当前用户,还有g(group)、o(others);如果省略,则表示给u、g、o均添加权限
chmod 777 1.txt #注:r4、w2、x1
chown:
chown xuan:xuan 1.txt
top:查看cpu、内存实时状态
free:查看内存使用状态
free -h(human)
free -m(MB)
free -k(KB)
df:disk free查看磁盘使用
df -h(human)
ps:查看进程
ps -ef
netstat:监听网络端口
-a:all
-n:numeric
-l:listening
netstat -anl
kill:给指定进程传递信号。
kill -l
kill -9 pid
date:
date +%Y-%m-%d -> 20191030
date -d yesterday +%Y%m%d -> 20191029
date -d tomorrow +%Y%m%d -> 20191031
wc:统计
wc -l(line)
which:
which 在$PATH变量指定的路径中,搜索某个系统命令的位置【which find】
whereis:
whereis mysql 只能用于程序名的搜索
ifconfig:查看ip、网卡等信息
id:查看当前用户的id和组的id
diff:比两个文档的不同
diff a.txt b.txt
sleep:shell进程休眠一段时间
sleep 3
seq:序列
seq 10 100
ln:创建链接
ln -s /home/xuan myLink
tee:一边输出执行结果,一遍保存执行结果
sh a.sh | tee b.txt
hostname:修改宿主机名称
[admin@operator ~]$ hostname operator
查看系统信息:
uname -a
cat /proc/version(更全)
exit
exit <=> exit 0 退出并返回正常的标志
exit 1 退出并返回异常的标志
exit 0和exit 1的区别:
脚本a调用脚本b,要在a中判断b是否正常返回,就是根据exit 0 or 1来识别,用$?判断
脚本中引入其他脚本/属性文件:
. ./menu.sh #注:最前边有个“.”,后边是引入的文件
export:把子脚本中的变量(局部变量)导出成全局变量
alias:别名
alias aa='free -m'
unalias aa #解除别名
若想重启后还能用,vi并保存到~/.bashrc文件中
crontab:定时器
crontab -e 编辑
*/1 * * * * /home/xuan/1.sh
crontab -l 展示所有
crontab -r 删除所有
系统日志:/var/log/messages
向系统日志写消息:logger "xxxxx" #消息会自动追加到/var/log/messages
下载、安装:yum、wget、rpm、apt-get...(有的适用于CentOS,有的RedHat,有的Ubuntu),
以yum为例:
yum install redis
yum remove redis
vi/vim编辑器
命令行模式:
G:跳到文档最后一行
gg:调到文档第一行
x:删除当前光标所在的字符
nx:从光标向后删除n个字符
dd:删除当前行
ndd:删除当前及后n行
D:删除当前行光标后边所有字符
r:replace,替换当前光标的字符
yy:粘贴
p:paste复制
u:撤销
插入模式:
i:从当前行进入插入模式
o:从下一行进入插入模式
底行模式:
搜索 /
显示行号 :set nu
打包/压缩
tar 打包/压缩
-c: create
-v: view #查看视图
-f: file
-z: zip #压缩
-x: extract #抽取、解压
-t: list #不解压的情况下查看文件列表
tar -cvf a.tar * #打包当前目录所有文件
tar -czvf a.tar.gz *
#打包并压缩当前目录所有文件。建议对.tar文件压缩后的文件后缀改为.tar.gz
tar -tf a.tar #查看a.tar内部文件列表
tar -xvf a.tar #解压a.tar
#注:"tar -czvf a.tar.gz *" 等价于 "tar -cvf a.tar *" + "gzip a.tar"
gzip 压缩
gzip a.txt -> a.txt.gz #将a.txt压缩,自动变成a.txt.gz
gzip a.tar -> a.tar.gz #将a.tar压缩,自动变成a.tar.gz
gzip -d a.tar.gz #解压a.tar.gz得到a.tar
tar -zxvf a.tar.gz # 一次性两步:先解压得到a.tar,再解包得到a.tar内部所有文件
zip/unzip 压缩/解压
zip target.zip sourceFile #把sourceFile压缩成target.zip
unzip zipFile
unzip zipFile -d dir #解压到指定目录
shell
解释器
#!/bin/bash(默认可以不写) 解释器
#!/bin/sh 解释器
#注释
执行脚本
./shell.sh(需要执行权限)
sh shell.sh 或 bash shell.sh(读取执行~只需要读取权限)
source shell.sh
变量
a=3
$a 等价于${a}。但是 ${a}ook 和 $aook就不一样
$? 上一个指令是否正确执行,上一个脚本是否正常退出(1-不正确,0-正确)
$0 文件名
$1~$9 第几个参数值。# echo ${1:-daily},取脚本第一个参数,如果没有,则赋值daily
$# 一共几个参数
$* 所有入参
符号
| 管道符号:把前边的输出作为后边的输入
> 覆盖输出;>> 拼接输出
echo "abc" > a.txt
echo "abc" >> a.txt
; 一行执行多条语句的分隔符 cat a.txt ; ls
&& 前边语句成功才会执行后边语句 cat a.txt && ls
|| 前边语句失败才会执行后边语句
$$ : echo $$ -> 输出当前脚本的执行进程id
"" 输出变量值 a=10;echo "$a" -> 10
'' 输出本身 a=10;echo '$a' -> $a
`` 执行内部语法。echo `date` 等价于 $(date)
nohup [commond] & 后台运行
2> /dev/null 把错误输出扔进无底洞(2和>之间不要有空格)
1> /dev/null 把正确输出扔进无底洞(1和>不要有空格,可以省略1)
2>&1 错误输出合并到正确输出流
1>&2 正确输出合并到错误输出流
eg:
已有的shell指令中,输出结果既有正确又有错误的几乎没有,所以可以自定义shell脚本实现。
sh abc.sh 1> a.txt 2>&1 等价于:sh abc.sh &> a.txt
注:
& 是一个描述符,如果1或2前不加&,会被当成一个普通文件。
1>&2 意思是把标准输出重定向到错误输出.
2>&1 意思是把错误输出重定向到标准输出。
&>filename 意思是把标准输出和错误输出都重定向到文件filename
read
-t 阻塞时间
-s 隐藏输入的字符
-p 给出提示符
-n 读取字符的个数,个数到达临界之后会自动执行
read abc 把接下来输入的数据赋值给abc
read -t 10 -n 3 -p '请输入密码:' pass 注:把前边的输入传递给变量pass,-p要放在后边
echo -e "\n" #注:-e 表示escapes,开启转义符
echo "密码是:$pass"
eg:不换行输入用户名
read -p "请输入密码:" name
等价于:
echo -n "请输入密码:" #注:-n的作用是echo不换行
read name
计算器
整数:
expr 10 + 20 #注意+号两边的空格
echo $[10 + 20]
echo $((10 + 20))
echo $[10 % 3] 取余
echo $[10 \* 2] 乘法需要对*转义
bc计算器:
echo "scale=2;(1.2+2.3)/1" | bc #把前边的输出作为后边的输入。scale只对乘除有效
条件判断
[]
[ -e a.txt ] 方括号必须有左右空格。[ ! -e a.txt ] #叹号!表示取反
eg:[ -e a.txt ] && echo yes
-e exist 文件是否存在
-d directory 是不是目录
-f file 是不是文件
权限:
-r 是否有读权限
-w 是否有写权限
-x 是否有执行权限
整数比较:
-eq(equal)
-ne (not equal)
-gt (greater than)
-lt (lesser than)
-ge (greater or equal)
-le (lesser or equal)
小数比较:借助bc计算器
[ `echo "1.2 > 1" | bc` -eq 1 ] && echo '大于'
字符串:
= [ "1" = "1" ] && echo "相等"
!=
if
格式1:
if [ 条件 ];then
echo "xxx"
fi
格式2:
if [ 条件1 ];then
echo "xxx"
elif [ 条件2 ];then
echo "yyy"
else
echo "zzz"
fi
#拓展:[]和[[]]的其中一点区别(双括号要强大的多)
if [ $a -ne 1] && [ $a != 2 ]
等价于: if [[ $a != 1 && $a != 2 ]]
等价于: if [ $a -ne 1 -a $a != 2 ] #-a是and,-o是or
循环
for
示例1:
for i in 1 2 3 4 5 #注:in后边是"值1"、"值2"、"值3"...
do
if [ $i -eq 2 ];then
continue
else
echo "$i"
sleep 1
fi
done
示例2:
for i in $(cat www.txt)
do
ping -c 2 $i #注:-c表示最多ping几次。windows上是-n
done
示例3:((条件))
#注:i++相当于i=i+1,只能在(())中使用,等价于:let 'i+=1'
for (( i=1;i<11;i++ ))
do
echo $i
sleep 1
done
#注:for (( i=1;i<=$num;i++ ))报错:Syntax error: Bad for loop variable 奇怪
case
示例1:模拟天气预报-输入城市名称,输出城市温度
echo '请输入城市:'
read city
case $city in
'上海')
echo '上海:35度'
;;
'北京')
echo '北京:20度'
;;
*)
echo '未知城市'
esac #注:case倒叙
示例2:case接受简单正则
case $1 in
[a-z]|[A-Z])
echo "字母"
;;
[0-9])
echo "数字"
;;
esac
while
示例1:输入数字,并求1到该数字的和
sum=0
i=0
while [ $i -lt $1 ] #注:左右空格不能省略
do
sum=$(($sum+$i))
i=$[$i+1] #注:千万别忘了自增条件,否则就死循环了。等价于:((i++))
done
echo "从1加到$1的和是:$sum"
示例2:模拟菜单
while [ 1 ] #注:死循环会导致CPU骤升
do
#注:这里是cat不是echo;EOF是瞎写的,可以成对换成!或者abc;EOF之间的是原格式的纯文本
cat <
1.执行1.sh
2.执行2.sh
q.退出
EOF #末尾的EOF必须顶行写,且前后均不能有空格或tab
read -p '请选择:' key
case $key in
1)
clear
echo '执行1.sh'
;;
2)
clear
echo '执行2.sh'
;;
q)
clear
echo '退出'
break #注:break跳出循环
;;
esac
done
示例3:
num=0
while [ $# -gt 0 ]
do
num=$(($1+num))
echo "剩余参数:$*"
shift #将参数向左偏移一个
done
echo "总和:$num"
结果如下:
[root@localhost xuan]# sh 5.sh 1 2 3 4 5
剩余参数:1 2 3 4 5
剩余参数:2 3 4 5
剩余参数:3 4 5
剩余参数:4 5
剩余参数:5
总和:15
示例4:死循环
while true # 或 while : 或 while [ 1 ]
do
let i++
echo $i
sleep 1
done
例子
1.判断两个数是否相等
if [ $1 -eq $2 ];then 注:if后有空格
echo "$1等于$2"
else
echo "$1不等于$2"
fi
等价于:
[ $1 -eq $2 ] && echo "$1等于$2"
[ $1 -eq $2 ] && echo "$1不等于$2"
#注:多条件
if [ "a" = "a" ] && [ "b" = "b" ]
2.判断上一个指令是否执行成功
fName=22.txt
touch $fName
if [ $? -eq 0 ];then
echo "$fName创建成功"
fi
3.判断输入的数字是否大于10
echo '请输入一个数字:'
read number
if [ $number -eq 10 ];then
echo '等于10'
elif [ $number -lt 10 ];then
echo '小于10'
else
echo '大于10'
fi
4.越过交互:给用户xuan设置密码。需要交互两次
方式1:
passwd xuan < password.txt
#注:password.txt文件中有两行相同的密码
方式2:
passwd xuan <
123
123
EOF #注:末尾的EOF必须顶行写,不能有空格或tab
sh a.sh <
土豆
root
EOF
方式3:
echo 123 | passwd --stdin xuan
#注:passwd的--stdin参数ubuntu不支持,centos才可以
函数
示例1:两数求和
function add(){
echo $(($1+$2))
}
add 10 20
示例2:遍历指定目录下所有目录
function listFiles() {
for file in `ls $1`
do
dir=$1"/"$file
if [ -d $dir ];then
ls $dir
listFiles $dir
fi
done
}
listFiles $1
信号捕捉
#trap 捕获信号;2表示ctrl+c;3表示ctrl+\;kill -l可以获取到所有信号指令
trap 'myFunc' 2 3
function myFunc(){
read -p '确定终止吗? y or n' input
case $input in
'y')
exit
;;
'n')
;;
*)
myFunc
;;
esac
}
#以下的死循环防止程序退出
while true # 或 while : 或 while [ 1 ]
do
let i++
echo $i
sleep 1
done
split
1.文件按行数分割
split -100 a.txt aaa #-100表示100行分割一次,aaa表示分割后的文件名前缀,后缀是自动生成的
eg:
split -3 a.txt xuan
得到:
-rw-r--r--. 1 root root 127 Oct 15 13:17 a.txt
-rw-r--r--. 1 root root 29 Oct 15 14:23 xuanaa
-rw-r--r--. 1 root root 47 Oct 15 14:23 xuanab
-rw-r--r--. 1 root root 17 Oct 15 14:23 xuanac
-rw-r--r--. 1 root root 8 Oct 15 14:23 xuanad
-rw-r--r--. 1 root root 25 Oct 15 14:23 xuanae
-rw-r--r--. 1 root root 1 Oct 15 14:23 xuanaf
2.文件按固定大小分割
split -b 1M a.txt
3.文本合并,可以借助cat
cat xuan* > a.txt
字体颜色和特效
echo -e "\033[背景颜色;字体颜色;特效 \033[0m"
示例1:
echo -e "\033[32;41;5m 文本字体 \033[0m"
#注:最后的0m表示关闭属性,"\033["是固定前缀和后缀
示例2:
read -t 10 -p "`echo -e "\033[32;41;5m 请输入密码 \033[0m"`" pass
uniq & sort
cat a.txt | uniq #相邻行去重
cat a.txt | uniq -c #相邻行去重并统计次数
cat a.txt | sort | uniq -c #所有行排序,然后相邻行去重并统计次数
cat a.txt | sort -t: -k3 -r
#-t:表示以:为分隔符(默认空格),-k3表示以第3列排序(默认整行),-r表示反转
搜索
find 文件搜索
find . -name "a[0-9]*" #注:简单正则+通配符
find / -size 10c/10k/10M/10G #注:有的大写,有的小写
find . -type d/f/l #注:d表示目录,f表示文件,l表示链接
find . -mtime -3/+3 #注:-mtime表示修改时间;-3表示3天以内,+3表示3天前。
find . -user root
find . -name "[a-b]*.sh" | xargs rm -rf
#注:xargs是将管道前的搜索作为参数传给后边,此处如果不加xargs,则后边的指令是没有意义的
grep 文本·行搜索
-v invert 反向选择
-i ignore 忽略大小写
-w word 单词匹配
-n 显示行号
-m 限制行数 grep -m 100 a.txt(有时不好使) grep -10 a.txt
-e 多个OR条件 grep -e condition1 -e condition2 xxx.txt
--color=auto 过滤字段添加颜色
"^xx" 某行以xx开头(行首匹配)
grep "^user" a.txt 或:grep -E "^user" a.txt
"xx$" 某行以xx结尾
grep "user$" a.txt
-E regex 正则 grep -E "sbi*" /etc/passwd
grep -Ein "(linux){2}" a.txt #注:()表示单元
grep -Ein "(linux)+" a.txt
grep -Ein "[0-9]+" a.txt
grep -E "\*" a.txt #注:\转义等价于:grep "*" a.txt (默认不支持正则)
grep -E "[0-9]+\.+[0-9]+\.[0-9]+\.[0-9]+" a.txt #注:搜索ip
grep -E "^$" a.txt #注:找空行
grep -E "^[^d]" a.txt
#注:找不是d开头的行。^放在[]外边表示"以xx开头",放在[]中表示"除了"
cut 文本·列操作
-d 指定分隔符,delimiter
-f 指定第几列
-c 按字符截取
示例1:以冒号分割后,取第1列和第3列
cut -d ':' -f 1,3 /etc/passwd
#注:1,3表示第1列和第3列;1-3表示第1列到第3列;3-表示第3列以后。
示例2:
cut -c 1-4 /etc/passwd #截取第1列到第4列字符,以字符为单位
示例3:查找linux系统中所有不能登录的用户名
cat /etc/passwd | grep /sbin/nologin | cut -d ':' -f 1
#注1: cat /etc/passwd | cut -d ':' -f 1 等价于cut -d ':' -f 1 /etc/passwd
#注2:/bin/bash结尾的用户是可以登录的;/sbin/nologin结尾的是系统默认用户,不可以登录
#注3:cut用空格分割的话,每一个空格都会计数1次。
Mem: 1837 107 298 0 1431 1532
free -m | grep -i mem | cut -d " " -f 12 -> 1837
free -m | grep -i mem | cut -d " " -f 2 -> 空格
awk 文本操作
awk是一门语言,是3个创始人的姓名首字母缩写而成
printf不换行打印;print 换行打印
printf '%3s %3s\n' 11 12 -> %ns是字符串,n默认是1可省略
printf '%2i %2i\n' 11 12 -> %ni是数字
printf '%.2f\n' 0.1234 -> 0.12 "%.nf"是格式化浮点数
3.1 awk (默认分隔符是空格)
3.2 awk '条件1 {动作1} 条件2 {动作2}' 文件名
echo "0.123+0.123" | bc | awk '{printf "%.2f\n", $0}'
#注:$0表示整行,$1表示第一列...
df -h | grep /dev/sda2 | awk '{print "sda2的磁盘使用率:" $3}'
free -m | sed -n '2p' | awk '{print "total:"$2"\n" "userd:"$3"\n"}'
3.3 awk 选项 '条件1 {动作1} 条件2 {动作2}' 文件名
cat /etc/passwd | awk -F ":" '{printf $1}'
#注:-F指定分隔符,field-separator
cat /etc/passwd | awk 'BEGIN {FS=":"}{print $1} END {print "结束了"}'
#注1:FS是field separator
#注2:BEGIN是在awk之前执行,一般用于修改内置变量;END是awk执行完之后执行
3.4 NR 行号,是awk中的一个常量(num row);NF列号(num field)
df -h | awk 'NR==2 {print $1}'
df -h | awk '(NR>=2 && NR <=4) {printf $1"\n"}'
cat a.txt | awk 'END{print NR}' #统计有多少行
cat a.txt | awk '{if(NR==1){print $0}}' #打印第一行
cat a.txt | awk '$0~/java/' #$0表示整行,~表示匹配,/被匹配文本/
cat a.txt | awk '$0!~/java/' # !~表示不匹配
sed 文本·行操作
-n和p一块使用: df -h | sed -n '2'p #查询第2行,p表示print,也可以写成sed -n '2p'
d:删除 df -f | sed '2'd #删除第2行
eg:
cat a.txt | sed -n '1,/java/'p #搜索第1行到包含java的那一行。
cat a.txt | sed -n '10,$'p #搜索第10行到最后一行。等价于:sed -n '10,$'p a.txt
cat a.txt | sed '2,3'd #搜索除了第2行到第3行的数据
a:在下边插入
df -h | sed '2a xuan'
i:在上边插入
df -h | sed '2i xuan'
c:替换
df -h | sed '2c xuan' #把第2行替换成xuan
s/旧串/新串/g
df -h | sed 's/oldStr/newStr/g'
-i:对源文件进行修改(危险)
sed -i 's/oldStr/newStr/g' a.txt
sed -i '2i 玄' 5.txt
-e:指定多个条件
案例
巡检内存
total=`free -m | sed -n '2p' | awk '{printf $2}'`
#注:awk '{}'别漏了单引号;printf别漏了f
used=`free -m | grep -i mem | awk '{printf $3}'`
percent_used=`echo "scale=2;$used/$total" | bc | awk '{printf "%.2f",$1}'`
echo -e "总共:${total}m"
echo "已用:${used}m"
echo "内存使用率:$percent_used"
threshold=0.04
flag=`echo "$percent_used > $threshold" | bc`
if [ $flag -eq 1 ];then
echo -e "\033[31m内存使用率超过$threshold \033[0m"
#注:31m后边如果有空格,则打印出来也有
fi
批量创建用户
read -p '请输入用户名前缀:' user
read -p '请输入创建用户个数:' num
echo "$user $num"
for i in `seq 1 $num` #注:seq默认从1开始,所以1可以省略
do
#创建用户:先判断用户是否存在
newUser=$user$i
cat /etc/passwd | awk -F":" '{printf $1"\n"}' | grep $newUser
if [ $? -eq 1 ];then #注:上边搜不到则$?=1
useradd $newUser
echo "创建用户$user$i"
#设置8位随机密码. /dev/urandom文件中会随机产生一些乱码数据,使用md5sum可以得到随机字符串
password=`head -1 /dev/urandom | md5sum | cut -c 1-8`
echo "用户名:$newUser\t密码:$password" >> user_passwd.txt
fi
done
从mysql查询数据
read -p '请输入你要查询的商品名称:' name
read -p '请输入数据库用户名:' username
/usr/bin/mysql -u${username} -p -e "use test;select * from item where name = '$name';"
#注:-e表示excute,不进入mysql命令窗口,直接执行语句
高效登录远程服务器
ip=`cat ip.txt | grep $1 | awk '{printf $2}'`
ssh $ip
执行:
sh aaa.sh beijing #注:beijing赋值给$1,ip.txt文件中地址和ip使用空格隔开
shell远程执行
#!/bin/bash
#基于某台机器,要挨个ssh到其他机器执行shell指令,需要借助EOF,否则会直接调到远程机器并终止当前shell
for (( i = 3; i < 100; i++ )); do
dssh api-mms-sf-69beb-${i}.docker.py > /dev/null 2>&1 << EOF
echo "api-mms-sf-69beb-${i}.docker.py"
sudo -iu xiaoju
rm -rf /home/xiaoju/data1/mms-logs/mms-context.log*
exit
exit
EOF
done
控制台操作函数
root@sim-mms01-v-sf-2d692-0.docker.py:~$ test() {
> echo "abc"
> echo "123"
> }
shell函数只能return数字,返回String会报错
可以通过"$(函数名)"获取函数中所有的打印值
function get_pid() {
if [ -f $pidfile ];then
pid=$(cat $pidfile | sed 's/ //g')
(ps -fp $pid | grep "${module}" &>/dev/null) && echo $pid
fi
}
function check_pid() {
pid=$(get_pid)
.....
return 0
}