上传脚本
scp xxx wang@172.18.0.7:/data/script38
口令 magedu
ifconfig xxx | sed -n '2p' 打印第二行
ifconfig eth0 | sed -n -e '2s/.inet / / ' -e '2s/ .net.$/p'
setfacl -m u:www:rwx /usr/local/nginx/html/app
把/usr/local/nginx/html/app
对用户www设置acl权限,附加读写执行
sed -n 是关闭自动打印 , -e 是多点编辑(也就是且的含义,满足多个条件)
'2s/xxx/abc/p' 把第二行的xxx替换成abc并且打印出来
ifconfig eth0 | sed -r '2!d ; s@(.net )(.)( netmask.*)@\2@'
这里@相当于/ sed -r '2!d' file 是指保留第二行
sed -n '/2/,/4/p' file 打印file里面包含2或者4的行
sed -n '1~2p' file
打印file里第1,3,5,7...奇数行
注意 1,3 是1到3行 1~3是1 ,3,5,7的含义
sed -n '2~2p' file 打印2,4,6,8....行(偶数行)
sed '2ahello' pets
在第二行的下一行添加hello
ifconfig eth0 | sed -nr '2s/^[0-9]+([0-9.]+).*/\1/p'
sed '2ahello\nworld' file
在第二行的下两行添加hello world
sed '2ahello\nworld' file
在第二行的后两行添加hello world
sed '2ihello\nworld' pets
在第二行的上两行添加hello world
sed '2chello' file
把file第二行替换成hello
sed '=' file
在每行的上一行添加行号
sed 'G' file 在file的每一行后面增加一空行
sed '/regex/G' test.txt
在匹配regex的行之后插入一个空行
seq 1 5 | sed -n '2!p' 不显示第二行
sed -nr 's@[#]@#&@p' /etc/fstab
把非#开头的行前面添加# 并且打印出来
取 /etc/fstab 基名
echo '/etc/fstab' | sed -nr 's@^(.*/)([[:alpha:]]+)@\1@p'
sed里面的&的用法
sed -r 's/.*/#&/' file
&表示前面搜索到的内容,在这里
&表示每一行 所以 此命令是在每一行
前面添加#
sed /etc/passwd | sed '/^root/!d' | sed 's/root/test/2'
sed '/^root/!d' 是把以root开头的行保留下来
sed 's/root/test/2 把这行的第二个root替换成test
seq 1 5 | sed '2r test.txt'
seq 1 5 生成 1到5 sed '2r test.txt'
是指把test.txt的内容读出来添加到第二行后面
cat pets | sed '1,3w test.txt
把 pets的第1到3行 写入文本test.txt
sed -r 使用扩展正则 把以非数字开头中间包含数字和点 后面是任意字符的行替换成
被小括号包裹的内容 并且打印出来
/etc/default/grub里面有下面一行
GRUB_CMDLINE_LINUX="crashkernel=auto rhgb quiet "
sed -nr 'CMDLINE_LINUX/s/(.*)"/\1 net.ifnames=0"/p' /etc/default/grub
是指把/etc/default/grub里面包含CMDLINE_LINUX的行在 后面追加 net.ifnames=0
即变成 GRUB_CMDLINE_LINUX="crashkernel=auto rhgb quiet net.ifnames=0"
然后执行 grub2-mkconfig -o /boot/grub2/grub.cfg 重启 网卡变成eth0 ,eth1, eth2...
sed -n '/avahi/s/[[:alpha:]]/\u&/gp' /etc/passwd
把/etc/passwd里面包含avahi的行的所有字母替换成大写 \u表达大写 \l表示小写
sed -n 's/root/&xxxxx/p' file
把file里面的root后面添加xxxx
sed -n 's/root/xxxx&/p' file
把file里面的root前面添加 xxxx
脚本安全
set -u:一旦在脚本开头定义了set -u,
那么在执行过程中,如果发现某个变量没有被定义,那么会报错,但是依然会继续往下执行
set -e 如果在执行过程中,发现报错,那么停止执行,退出。所以 一般是set -ue
find利用通配符匹配文件或者目录的时候,一定要记得加双引号
find /data -nouser -nogroup -ls
罗列 data 目录下 既没有所有者,又没有所属组的文件和目录
find /data ! -name "*.sh"
查找 /data目录下 文件或者目录不是.sh结尾的内容
find /tmp ( -not -user root -a -not -name 'f*' ) -ls
find /etc -path '/etc/sane.d' -a -prune -o -name "*.conf"
查找/etc目录下 除了/etc/sane.d目录内的所有以.conf结尾的文件或者目录
查找 tmp目录下 所有者不是root 并且不是以f开头的文件或者目录
注意 : 要把搜索条件加小括号
find 加上 -regex选项的时候,可以使用正则,但是要求匹配全路径(而不是写路径的一部分)
find -size 10k (9-10k) -10k (0-9k) +10k(大于10k)
find -atime 10 (10-11天) -10(0-10天) +10(大于11天)
find /data -mindepth 3 -maxdepth 3
只搜/data目录下的第三层目录(从/data这层开始算 /data目录本身算第一层)
shell脚本的位置参数 只能从外部读取,不能在脚本里面修改,
[ -a file ] file存在即为真 同 -e
把/etc/selinux/config里面的SELINUX=enforcing 修改成disabled
echo user{1..10} | xargs -n1 useradd
批量创建账号
echo user{1..10} | xargs -n1 userdel -r
批量删除用户
压缩工具是单个文件压缩的
echo a b c | { read x y z; echo y $z; }
管道符两侧的都会开启子shell,所以需要加上花括号来保证右侧的能够获取x y z 的值
find /data -perm /700 -ls
是指 所有者读,写,执行有其中一个即可。
例如/644是指所有者读写有其中一个,所属组读,其他读
find /data (-user root -o -name 'f*') -ls
find -perm \022 -ls \或 -且
注意: 一定要加()在ls之前
注意: 在使用中括号的时候,/$变量 一定要用双引号包裹
[ xxx ] 只要中括号里面有值 即为真 echo $? -> 0
2 等等位置参数只能读取 不能修改
$_ 最后一个参数
.或者souce xx 是把文件读取到当前shell
bash或者./ 开启子shell 一般脚本都运行在子shell里面
find 里面的正则 是精确匹配
find -name ".txt" | xargs | ls -Sl
查找名字为txx结尾的 然后排序
find -name ".txt" -print0 | xargs -0 以0分隔
locate 查找文件依赖数据库,适合搜索稳定的文件 创建数据库updatedb
locate 默认模糊搜索 ,locate -r 支持正则
引用传递给脚本的参数的时候,如果要引用第10个参数 ,记得要这样写 ${10} 不可写成$10,否则会被认为是$1 和 0
echo $? 打印上条命令的执行成功与否 0表示成功 非0表失败
注意:echo$? 只能判断上一条的命令执行成功与否 ,倒数第二条都无法判断,
也就是说,一个脚本中间出错了,但是最后一条命令执行成功了 那么echo $?显示的是0
默认命令执行成功了,返回0,但是也可以自定义数值,通过exit xx 那么命令执行成功了,即返回xx(但是xx也有范围最大是255)
echo 'helloabc' | grep -E '<hello' 匹配hello作为helloabc的词首
echo 'abchello' | grep -E 'hello>' 匹配hello作为abchello的词尾
匹配词首和词尾的时候,即使使用grep -E / egrep 也要加上
同样 使用grep -E 匹配“点” 也需要加上反斜杠
字母,数字,下划线是单词的内部,除此之外,都是单词的外部
grep -v 'root' -m3 /etc/passwd 匹配/etc/passwd里面不含root的前三行
配置/misc(光盘自动挂载点)
systemctl start autofs
systemctl enable autofs
grep -w 表示匹配一个单独的单词 前后必须是除了 字母,数字,下划线的其他字符作为单词分界线
grep -f file1 file2 用file1里的字符串去匹配file2 (也就是找二者相同的字符串)
bash -n xxxx 检查语法
bash -x xxx 调试执行
取出两个不同目录中相同的文件列表
假设这两个目录是 /tmp/root.log 和 /tmp/data.log
grep -f /tmp/data.log /tmp/root.log
这条命令是指 用 /tmp/data.log 里面的字符串去匹配/tmp/root.log的文本
即对这两个文件取交集
取出两个不同目录中不同的文件列表
grep -vf /tmp/data.log /tmp/root.log
即加上-v选项即可(表示取反)
grep -Ev '$|#' /etc/xxxx/xxx
是指 匹配除了空行和以#开头的文本
正则 [.*?] 注意放在中括号里面的仅仅表示“点”,‘星号’,“问好” 当中的其中一个
cmd=命令 $cmd执行命令
变量赋值 等号前后不能有空格
显示变量值的时候,在输出的时候加双引号 保留原有格式
set 显示所有变量 env显示环境变量
普通变量(通过变量=xx 定义的)只在当前shell有效
把/data/script38添加到环境变量里
PATH=/data/script38:$PATH
source /etc/profile.d/env.sh
生效
把脚本的路径添加到环境变量里之后 可以任何目录里直接执行此脚本。例如 xxx.sh 不用添加任何命令
在shell脚本中定义变量的时候,在等号左右不要添加任何空格
编写生成脚本格式的脚本,包括
作者,版本,时间,描述
! /bin/bash
set ignorecase
set cursorline
set autoindent
autocmd BufNewFile *.sh exec ":call SetTitle()"
func SetTitle()
if expand("%:e") == 'sh'
call setline(1,"#!/bin/bash'")
call setline(2,"#")
区别变量名和变量
用{}或者双引号
num=1
echo "$num"no > 1no
echo ${num}no > 1no
用一个变量引用命令的结果的时候,对$变量加上双引号可以保留命令结果的原格式
bash 开启子进程
子进程不能使用父进程定义的普通变量(即通过xxx=xx这种形式定义的)
打印当前的bashpid
echo $BASHPID
环境变量声明
export A=xx
变量引用 $A 或者${A}
pstree -p 显示进程间的关系
env 显示所有已经定义的环境变量
进程间的传承只能从上往下,即(从父进程到子进程。。。。无法逆过来)
环境变量只需声明一次,它的子进程,孙子进程就可以一直用,不必重复声明
假设xxx.sh是一个有执行权限的脚本 xxxx.sh a b c 表示给这个脚本传递三个参数
a b c 通过$1,$2,$3分别获取a b c
算数运算 $[xxOPERATORxx] 一般通过这种方式来计算
echo $RANDOM 打印随机数
echo '算数表达式' | bc
条件测试 一般用[ expression ] 或者 [[ expression ]] 注意 expression 前后都有空格 或者 test expression
利用 test或者[ expression ] 进行条件测试的时候 ,建议对$变量加双引号
想要两条命令作为一个整体,那么可以对这两条命令加小括号或者花括号
例如 (ls;hostname)
{ ls;hostname; }
注意使用花括号的时候,两侧有空格
二者有区别
小括号是运行在子shell里面的(开启子进程)
花括号 不开子进程
[[ xx=~正则 ]] 双中括号可以使用=~使用正则
当[[ ]] 里面是== 或者!= 那么星号 表示通配符
x=abc;[[ "$x" == ab* ]] && echo true
注意 双中括号里面 当使用通配符的时候,通配符看情况是否加
而变量最好加
双中括号里面的正则使用的是扩展正则表达式
小括号里面如果是变量赋值或者是内部命令,那么当他们执行结束之后,不会对小括号外面的造成影响
[ -e $file -a ! -x $file] 是指file存在且没有执行权限
ping -c -W xxxx
-c 是指ping几次
-W是设置超时时间
[ -z "$HOSTNAME" -o $HOSTNAME = "localhost.localdomain" ] && hostname www.magedu.com
是指 如果HOSTNAME为空 或者HOSTNAME的值为localhost.localdomain 那么更改主机名
管道符里的命令都运行在子进程里
echo mage 30 | { read NAME AGE; echo $NAME $AGE;}
因为管道符里都开启了子进程,所以需要用花括号包裹,这样被花括号包裹的被视为一个进程 ,就可以查看了
父进程无法读取子进程的信息
read -p 指定要显示的输出
-s 静默输入,一般用于密码
默认情况下 当定义普通变量的时候,子shell无法继承父shell的信息,但是出现圆括号的时候,是个例外,被圆括号包裹的父shell里面的变量在圆括号里能被打印出来。
解压缩 注意 后缀
tar -cvf xxx.tar file/directory
tar -rf xx.tar file
把file 添加到tar包里
tar -xf xx.tar 默认解压到当前目录
tar -xf xxx.tar -C xx
解压到指定目录
打包并压缩 .gz 格式 tar -zcvf ...
.bz2格式 tar -jcvf ..
.xz格式 tar -Jcvf
解压缩并解包 tar -xvf ..
split -b size xxx 切割文件
sed -n '3p' /etc/passwd
打印第三行
sed -n '/^U/p' /etc/passwd
打印U开头的行
斜线之间写正则r
sed -n '/r/,/f/p' /etc/passwd
打印 以r开头到f开头的行 。如果后面还有继续打印这个循环
sed '/# User/a xx' file
往file里面 匹配# User的行后面添加内容
sed '/# User/i xxx' file 行前插入
sed -i.bak '/# User/c xxx file
匹配 # User的行用xxxx替换 在替换之前备份名字为 file.bak
seq 10 | sed '2a\ xxxx'
表示在第二行后面添加内容 反斜线后面有什么全部添加 (包含空格等)
seq 10 | sed '2,6w /data/sed.log'
把2-6 保存到sed.log里面
seq 10 | sed '2,6r /etc/issue'
在2-6行的每行后面都添加/etc/issue的内容
sed -n '/^U/!p' /etc/passwd
打印不是U开头的行
sed 's/UUID/uuid/g' /etc/fstab
把UUID替换成uuid
sed -r 's/(SELINUX=)disabled\1enforcing/' /etc/selinux/config
sed -r 支持扩展正则表达式