很全的shell知识总结宝典

HOST=$(/bin/hostname)
将()里的命令执行后的结果赋值给HOST变量

======我是分割线=====

/etc/rc.d/
level3的用户login后, 将自动启动一个指定的shell

======我是分割线=====

  • $? 对上一次命令执行成功与否
  • 成功则$?返回值为0

======我是分割线=====

判断文件是否存在且是否为文件
[ -f file ]
判断文件是否存在且是否为可写文件
[ -w file ]
判断文件是否存在且是否为可执行文件
[ -x file ]
判断文件是否存在且是否为可读文件
[ -r file ]
判断文件是否存在且是否为目录文件
[ -d file ]
判断文件是否存在且是否为空文件
[ -s file ]
判断文件是否存在
[ -e file ]
[]和 test功能一样 -a和-o(和,或)

======我是分割线=====

整数值比较判断

[ -eq ]
[ “$a” = “0” ]
(( a % 2 == 0 ))

[ -n string ] string 的长度大于0
[ -z string ] string 的长度为0
string1=string2 字符串相等
string1!=string2 字符串不相等
[ int1 -gt int2 ] int1>int2 greater than
[ int1 -ge int2 ] int1>=int2 greater equal
[ int1 -eq int2 ] int1=int2 equal
[ int1 -ne int2 ] int1!=int2 not equal
[ int1 -le int2 ] int1<=int2 less equal
[ int1 -lt int2 ] int1< int2 less than

======我是分割线=====
字符串比较
[ “$a” = “$b” ]
[ -n “$a” ]和 [ “$a” ]
效果一样 判断字符串$a是否为空

[[ "$a" == *"redhat"* ]][[ "$a" = *"redhat"* ]]

判断-在$a中是否含有redhat字符串

if后接的是命令
if rpm -q gcc && id tom||echo “sss”; &&
如果前面的命令执行成功则执行&&后的命令否则执行||后面的命令

======我是分割线=====

sed -ri /^#ServerName.*:80$/s/^#// /etc/selinux/config
找出/etc/seliunx/config文件中以#ServerName开头以:80结尾的行,并将#替换成空。

df -Th|grep "/$"|awk '{print $6}'|sed 's/%//'
截取某个字段并替换

======我是分割线=====

(( a == 50 )) 数值的比较,在(())里用不用$都一样

======我是分割线=====
echo $$ 当前的进程号
数据类型: 仅一种, 即字符串
本地变量, set, 查看当前shell下的所有变量, unset清除一个变量
a=10+20; A=”abc def”; $a

间接引用:
a=b; b=sxjy; echo ${!a}
显示sxkj
加上{}使变量更加清晰 !a是取a的值 和{}一起用

======我是分割线=====
数学运算:
将运算的结果赋值给一个变量

declare -i c=10+20
c=$[ a+b ]
c=$(( a+b ))
(( c=a+b ))
let c=a+b

能输出结果
expr 1 + 1
交互模式可以用管道或重定向传值

echo "scale=2;10/3"|bc   计算10/3的值
echo "3.14 > 3.15" | bc  正确输出1
echo "123"|read a
echo -e  后面的字符启用转义
echo -n  输出不换行
read a b c  读入几个变量

======我是分割线=====
以空格结尾
read -s a 读入时不显示输入
read -p ” 提示语言” a 设置有提示语言
read -t 3 a 设置3秒不给a赋值脚本继续执行
read a b < file1 没有循环 将第一个字段赋值给a,第二个字段赋值给b
cat file1
a1 tom a1
a2 jerry aa
a3 mike a34
read a b c < file1
此时 a=a1 b=tom c=a1

======我是分割线=====
\s 任意的空白符, 包括空格、制表符(tab)、换行符、中文全角空格
\t 制表符(tab)
\n 换行符
\r 回车符
\w word串, 由字母数字下划线组成的字符串

======我是分割线=====
grep awk sed 是基于正则表达式设计的。
用双引号将正则表达式引起来 。
^行首定位符

  • ^love 匹配所有以love开头的行

$ 行尾定位符

  • love$ 匹配所有以love结尾的行

.单个任意字符

  • l..e匹配以l开始后跟两个字符再跟一个e的字符串

*重复0到多个星号前面的字符

  • a* 匹配0个或多个a的字符串

[]匹配一组字符的任意一个

  • [Ll]ove 匹配Love或love的字符串

[x-y]匹配制定范围的一个字符

  • [A-Z]ove 匹配大写字符开头后跟ove的字符串

[^]匹配不在指定组内的字符;

  • [^A-Z] 匹配不是大写字母的任意字符

\转义字符用来转义元字符

  • love\.匹配love后跟一个.的字符

!取反

+ 表示一个或多个

  • xyz+ 一个或多个z

? 表式0个或一个

  • xyz? 0个或一个z

RE元字符
\< 词首定位符

  • \< love 匹配love开头的词

\> 词尾定位符

  • love\> 匹配love结尾的词

\< bin\> 匹配一个单词
\(..\) 给匹配的字符打上标签

  • (lov)able\1er/ 模式lov被保存为标签1用\1表示
  • 查找一个字符串lov后跟上able,再跟上lov再接上er即:lovablelover

x{m}和x{m,}和x{m,n}

  • 字符x重复出现:m次,至少m次,至少m次,并不超过n次

o{5,10}

  • 匹配包含5~10个o的字符串

| 表示或者

=====我是分割线=====

echo "tom and jerry"|sed -r 's/(tom) and (jerry)/\2 and \1/'
echo "tom g1,g2,g3 jerry"|cut -d" " -f2
echo "abc def"| sed -r 's/([a-z]+) ([a-z]+)/\2 \1/'
echo "abc def"| sed -r 's/([a-Z0-9]+) ([a-Z0-9]+)/\2 \1/'
echo "abcgood"|grep -E "abc(good)*" --color 匹配abc后有一个或多个good的行
echo "abchidhn"|sed -r 's/(.)(.*)/\1/' 用()切割字符
echo "abc" |grep -E "abc{3}" {}之前字符c出现的次数为3echo "abc defd xyz"|grep -E "\<[a-Z]{3}\>"匹配有三个字母的
echo "abc"| grep -E "abc+" --color
grep -E "^root|^tom" /etc/passwd
echo "abc user@sina.com.cn def"|grep -E "[a-Z0-9._]+@[a-Z0-9.]+\.[a-Z]{2,3}" --color  

=====我是分割线=====
sed 循环 一行一行的处理文件。行处理。
sed -n ‘/abc/p’ file

  • 默认会打印模式空间的内容
  • 行中匹配abc的打印出来

-r 支持扩展分割符
-n不让他默认打印模式空间

sed root@10.0.2.253 sed ‘s/abc/def’ file 远程登录后修改file里的内容
sed -n ‘5p’ file 把第五行打印出来
sed -n ‘$p’ file 把最后一行打印出来
sed -n ‘1,3p’ file 把一到三行打印出来
sed -n ‘1,~3p’ file 从第一行开始打印三行
sed -i ‘3i aaaaaaa’ file 在第三行的前面加上aaaaaaa
sed -i ‘$a aaaaa’ file 在最后行加入aaaaa
sed -i ‘/^tom/i aaaaaa’ file 在以tom开头的行前一行加上aaaaaa
sed -i ‘s/abc/def/’ file 改每一行的第一个abc成def
sed -i ‘s/abc/def/g’ file 改每一行的所有abc成def
sed -i ‘s/abc/def/3’ file 改每一行的第三个abc成def
sed -i ‘1,2s/abc/def/’ file 改一到两行abc成def

s 换匹配的字段 c换匹配的行:
sed -i ‘1,2s/^.*$/def/’ file 改一到两行成def
sed -i ‘4c aaaaaaaaa’ file 把第四行改为aaaaaaaa
sed -i ‘/^SELINUX/c selinux ’ 把所有以SELINUX开头的行改为selinux
sed -i ‘4d’ 把第四行删除
sed -i ‘/^tom/d’ file 删除以tom开头的所有行
sed -i ‘/^$/d’ file 删除空行
sed -i ‘/^\s$/d’ file 删除开头为空行\s表示空格或tab
sed -i ‘/^abc/s/tom/jerry/’ file 先找到以abc开头的行将这一行的tom改为jerry
sed -i ‘/^mike/s/^/#’ file 将mike行注释
sed -n ‘1p; 3p’ file 打印第一行和第三行
sed -i -e ‘1s/jerry/tom/; -e 3s/mike/xyz/’ file 多条一起执行用-e
sed -i ‘/abc/,/^def/s/123/456/’ file 将abc开头的行和def开头的行之间的行的123改为456
sed -n ‘1,/def/p’ file 从第一行开始直到碰到def的行全部打印出来

======我是分割线=====
awk 按行处理行里字段 。循环命令。
默认以空格作为分割符 默认打印整行$0 -F分割符 制定分割符

awk 'BEGIN{print "aaaa"}/tom/{print $2}END{print "bbbbbbb"}'  file1
  • 先执行BEGIN里的语句,从文件中读取第一行是否匹配/tom如果有则执行没有就不执行直到读完后,再运行END的语句。
  • 可以选用BEGIN。 匹配项 ENG。
awk '/^mike/{print $2}' file
awk 'NR==2{print $2}'  file    NR是行号 NF字段数
awk 'NR==2||NR==4{print $2}' file   只读两个固定的行号
awk '{print $0}' file     $0 整行
awk 'BENGIN{FS=":" OFS=" "}/bash$/{print $0}' file  FS 指定了分割符为冒号,OFS指定了输出的字段分割符为空格
tr ":" "" 将冒号改为空格
awk 'BEGIN{i=10;echo$i}'
awk -v v1=$a -v v2=$b  'BEGIN{print v1+v2}'  将bash的值传给awk
awk -F: -v v1=$a '$0~v1'{print $0}  ~是匹配条件
awk 'BEGIN{i=0;}{i++}END{print i}' file
awk '/^root/{$3+=10;print $3}' file
awk '$1~"root"{print $1}' file
awk '$1==500{print $1}' file  第一个字段为500
awk '$NF~"bash"{print $1}' file  最后一个字段是否有bash
awk '$3>=500&&$3<=503{print $2}' file
awk -F: -v v1=$a '$1~^v1'  file 打印出以变量a开头的行
awk -F: '{if($1~/^root/)print $1}' file   打印出第一个字段以root开头的行的第一个字段

next  直接读下一行continue
exit 结束不读了break
int()整数化
awk 'system("useradd" $2)' file   system()调用系统的命令

======我是分割线=====
变量
${a}aaa变量a
export a 将本地变量a变成环境变量在子bash也可用
$PATH 路径变量 PATH=$PATH:/$HOME/bin 增加路径
$$ 显示当前的进程号
$PPID 父进程号
$USER 当前用户
$UID 当前用户的UID
$HOSTNAME 当前的主机名
$1 $2 $3 $4…. 要传递的参数
shift 将参数向前移动一位
$0 当前的脚本的名称
$# 要传递参数的个数
${!a} 间接取变量a值
$@和$* 所有的位置参数。区别$@最好用双引号,$*最好不要用双引号。“$@” 能包括空行 “$*” 所有的参数当成一个看待
for i 相当于for i in “$@”
$RANDOM 随机数
$? 返回值

=====我是分割线=====
for 遇空格或回车算一次
for i in tom jerry do
for i in *.sh
{1..10}相当于1 2 3 4 5 6 7 8 9 10
for i in {1..10}
seq -w 10 等宽09 10
seq 2 2 10 从2到10 每隔一个取一个数
for i in ‘< file’do
for ((i=0; i<10;i++))

=====我是分割线=====
while ((i<=10));do
while true do a=” ” while [$a ];do 相当于 while [ -n $a ] do while [ 1 ] do 死循环
cat file|while read a b c;do 每次读一行文件将参数(以空格分割)分别赋值

=====我是分割线=====
case “$c” in
10|20|30)

;;

用.执行脚本在当前下执行
定义函数 function name{} name()
调用函数 name
函数的返回值默认成功为0,不成功时为别的,可以自己设置。 return是返回到$?的值
echo ${a: -1} 得$a的最后一个字
函数中声明局部变量用local声明,否则在shell中变量都可以在脚本中任何一处使用。
如果一个脚本要用到另一个脚本里的函数则在脚本里用 . 执行一下要调用的脚本

======我是分隔线=====
bash自带的处理字符串
echo ${#a} $a中字符串的个数
echo ${a:3} $a中从第三个开始取直到结束
echo ${a:3:2} $a中从第三个开始去两个字符
echo ${a: -1} 取最后一个字符
echo ${a#*.} 从左边开始删除直到遇到.为止
echo ${a##*.} 从左边开始删除直到遇到最后一个.为止
echo ${a%.*} 从右面开始删除直到遇到.为止
echo ${a%%.*} 从右面开始删除直到遇到最后一个.为止
echo ${a/abc/111} 将变量a中的第一个abc替换成111
echo ${a//abc/xyz} 将变量a中的所有的abc替换成xyz

======我是分割线=====
shell中常见的工具
seq
seq 10

  • 1~10

seq 3 10

  • 3~10

seq 3 2 10

  • 3 5 7 9

seq -w 10

  • 同宽输入

seq -s

  • 设置分割符默认为换行

======我是分割线=====
tr 针对字符进行操作

echo "abc 11a22bc" |tr “abc” “xyz”
结果:xyz 11x22yz

tr “abc” “xyz” < file

  • 处理文件

tr “a-z” “A-Z” < file

  • 将小写字母转成大写字母

tr “:” “\m”

echo “abdcdd”| tr -d “abc”

  • 将abc三个字符删除

cat file |tr -d “a-z”

echo “aaaaaaaaxcxxx cccccccc”|tr -s”abc”

  • 将重复的abc字符压缩成一个字符

======我是分割线=====
sort 排序 。源文件没改变
默认以空白作为分割符以第一个字段进行排序 (按字符串排asic)
sort -n file 以第一个字段的数值排序
sort -r 倒序
sort -k2 以第二个字段排
sort -t: 以冒号分割字段

======我是分割线=====
uniq 去重复行 不改变文件
uniq file 只改变相邻的重复行
uniq -c 显示相邻的重复多少行
uniq -u 只显示没有相邻重复的行

======我是分割线=====
cut 分割字符 默认分割符为tab键
cut -d: -f1-f3 file 指定分割符为:只要1 3字段
echo “addfgg” |cut -c3 取第三个字符

======我是分割线=====
grep -n ”root“ /etc/passwd 过滤出来加行数
grep -c ”root“ /etc/passwd 过滤出来的行号
grep -v ”root“ /etc/passwd 取反
grep -q ”root“ /etc/passwd 过滤出来的不显示
grep -w ”root“ /etc/passwd 过滤出来有单词root的行
grep -o ”root“ /etc/passwd 过滤出来root单词
grep -ro ”root“ 目录 过滤出来目录中文件里的有root的行
grep -i ”root“ /etc/passwd 忽略大小写
grep -E ”root“ /etc/passwd 启用扩展正则
grep -f file file1 过滤出file和file1中共同拥有的行
grep -f file file1 -v 过滤出file有file1没有的行
grep -x ”root“ file 过滤file中只含有root的的行

======我是分割线=====
find . -nouser 把没有主人的文件找出来
find . +size +10000c 找出文件大于10000个字节的文件
find / -maxdepth 1 -name “*.conf” -maxdepth 不会找子文件
find . -perm 600 把权限为600的找出来
find . -name “*.sh” |xargs rm -rf {} 把文件找出后交给rm处理
find . -name “*.sh” |xargs -I{} rm -rf {} 用-I 指定用什么表示查出的内容4

======我是分割线=====
trap

  • 屏蔽信号

trap ” 2

  • 屏蔽中断信号

trap ‘ls;pwd;date’ 2

  • 当发出中断信号(ctrl+c) 执行ls;pwd;date;

trap 2
- 还原

======我是分割线=====
curl -o a.html http://www.sohu.com/index.html

  • 将搜狐的首页下载下载到a.html中

curl -O http://www.sohu.com/index.html

  • 将搜狐的首页下载下来

curl -T file ftp://10.0.2.253/

  • 将file文件用ftp协议上传到10.0.2.253中

======我是分割线=====
数组名=(值 值)定义数组
echo ${数组名[下标]}
arr=([0]=tom [1]=jerry [2]=mike [4]=lee)
arr=(tom jerry make)
echo ${arr[0]}
arr[x++]=tom
arr[x++]=jerry arr[0]=tom arr[1]=jerry
echo ${arr[@]} 数组的所有值
echo ${#arr[@]} 数组的个数
echo ${!arr[@]} 数组的下标
while read a b c; do
arr[x++]=$b 下标从0开始自动加1
done < file2

======我是分割线=====
bash下的特殊符号
* 多个字符 。”*” 不在具有通配符的作用
?一个字符
“” 将字符引起来将空白符也包含 ,所有的符号(如$)依旧有意义。

“ (反引号) 里的符号就是符号没意义
a=$(rpm -qf $(which ifconfig))
& 放在后台执行,在子shell中执行
;命令结束符
将命令放在()是在子shell中执行的命令(cd /tmp;ls)
{0..9..2} 0~9 增量是2
{1,3,5} 1 3 5
将命令放在{}是在当前shell中执行的命令(以;隔开)
a=5 eval echo {0..$a}
((a=10+2)) 赋值
((a==10 % 3)) 比较
| 两边的命令都是在不同的子shell中执行的
gunzip < aa.gz >a2

cat >file <<EOF   产生一个文件
>ABC
>EOF 

cat < file

=====我是分割线=====
shell的执行

  • bash shell.sh 在子shell中执行,不要x权限
  • . shell.sh 在当前的shell中执行,不要x权限。和source命令执行一样
  • 用路径执行,要x权限才能执行,在子shell中执行。

一般用第三种执行, 用bash -x 调试 在调用其它的shell时一定要用第二种。

=====我是分割线=====
用输入用户名和密码的叫登录shell,不用输入的叫非登录shell。

登录的shell:
登录shell时调用一下环境变量配置文件:
全局的变量配置文件 /etc/profile
第二个文件/etc/profile.d/*.sh
用户的环境配置文件
第三个文件~/.bash_profile
第四个文件~/.bashrc
第五个文件/etc/bashrc
退出时
文件.bash_logout

=====我是分割线=====
非登录shell()
第一个文件 ~/.bashrc
第二个文件/etc/bashrc
第三个文件 /etc/profile.d/*sh

R中的metacharacter
^
$
[a-zA-Z0-9]有且仅有1个字符
[^a-z]
. 有且仅有一个字符, 一个空格也是一个字符(换行符\n除外)
abc* 0个或多个c, 将*前面的那一个字符c重复0次或多次
.*

echo "tom and jerry" | sed -r 's/(tom) and (jerry)/\2 and \1/'
从左至右\1 \2 \3 ... \9

echo "tom g1,g2,g3 /home/tom" | sed -r 's/(.*) (.*) (.*)/\2/'
echo "abc def" | sed -r 's/([a-Z]+) ([a-Z]+)/\2 \1/'
echo "abcgood" | grep -E "abc(good)*" --color

echo "abcdef" | sed -r 's/(.)(.*)/\1/'
echo "abcdef" | sed -r 's/(.*)(.)/\2/'

grep -E abc{3} file1 {}前面的那个字符c连续出现3次
{3,}
{3,5}

grep -E "\<[a-Z]{3}\>" file1 --color 3个字符的单词

======我是分割线=====
ERE
xyz+

  • 1个或多个z

xyz?

  • 0个或1个z

| :或者
email正则:

grep -E "[a-Z0-9._]+ @    [a-Z0-9.]+    \.    [a-Z]{2,3}"

url正则:

  • grep -E “http:// [a-Z0-9.]+ . [a-Z]{2,3}”

======我是分割线=====
bash符号与正则元字符的比较
ll *.sh
ll | grep -i “.*\.sh$”

find -iname “*.sh”
find -iregex “.*\.sh$”

======我是分割线=====
stream editor, 实现了正则, 主要用来进行文本替换。
一行一行(循环)的读取、处理, 对一整行的处理
先使用行号或正则进行定位, 然后进行p s d c a i
/定界符, 可使用任意的字符如?

sed ‘/abc/p’ file1
读取file1的第一行到pattern space(临时缓冲区, 内存)
对pattern space中的这一行进行/abc/p操作
将pattern space中的这一行打印出来
清空pattern space
读取file1的下一行到pattern space
……

ssh root@10.0.5.6 sed -i ‘s/abc/def/’ file1

sed -n ‘5p’ file1
sed -n ‘1,5p’ file1
sed -n ‘$p’ file1
sed -n ‘/^root/p’ file1

sed ‘3i abc’ file1
sed ‘$a abc’ file1

sed -i ‘2,4s/.*/abc/’ file1
echo “30%” | sed ‘s/%//’

sed ‘/localhost/a ds.com’ file1
sed ‘/root/c aixocm’ file1

sed ‘/abc/d’ file1
sed ‘/abc/!d’ file1
sed ‘3d’ file1
sed ‘1,3d’ file1
sed ‘3,$d’ file1
sed ‘/^$/d’ file1
sed ‘/^\s*$/d’ file1

sed ‘s/root/ROOT/’ file1
sed ‘s/root/ROOT/g’ file1
sed ‘s/root/ROOT/2’ file1
sed ‘/tom/s/jerry/mike/g’ file1

echo “ab/c def” | sed ‘s/ab\/c/xyz/’
echo “a b c” | sed ‘s/ //g’

引用变量
var1=”root”
sed “/$var1/c aixocm” file1

行首加#
sed ‘/ADDR/s/^/#/’ file1

去行首#
sed ‘/ADDR/s/^#//’ file1

多次操作
sed ‘3s/abc/def/; 5s/abc/yyy/g’ file1
sed ‘s/abc/def/; s/hij/xyz/’ file1
sed -e ‘1,3d’ -e ‘s/tom/jerry/’ file1

& 保存查找串以便在替换串中引用
sed ‘s/tom/&jerry/’ file1

范围匹配
sed ‘/abc/,/xyz/s/tom/jerry/’ file1 abc到xyz中的
sed ‘/tom/,/jerry/d’ file1
sed -n ‘/abc/,/xyz/p’ file1
sed ‘1,/tom/d’ file1 第1行到第1个匹配tom的行

security = share
hosts allow
/etc/sysconfig/selinux
UseDNS no
sed -ri “/IPADDR/s/[0-9.]+/$ip/” ifcfg-eth0

======我是分割线=====

awk 'BEGIN{commands}pattern{commands}END{commands}' file1

均可选

awk -F: 'BEGIN{print "start..."}/root/{print $1}END{print "end."}' /etc/passwd

与sed一样, 也是一行一行的读取、处理(循环)
sed对一整行进行处理, awk将一行分成数个字段来处理
默认的字段分隔符为空白, 默认就使用了扩展正则, 所以不要什么-E -r之类选项。

执行过程:

  • (有的话)执行BEGIN{commands}语句块
  • 从文件或stdin中读取第1行
  • 有无模式匹配, 无则执行{}中的语句
  • 有则检查该整行与模式是否匹配, 匹配, 则执行{}中的语句, 不匹配则不执行{}中的语句
  • 读取下一行, 重复这个过程, 直到所有行被读取完毕
  • (有的话)执行END{commands}语句块

awk字段分隔符
-F
BEGIN中FS与OFS
echo “abc def:hij 123” | awk -F”[ \t:]+” ‘{print $3}’

======我是分割线=====
变量

'{print $0, NR, NF, $NF, $(NF-1)}'
'BEGIN{a=3.14; b=3.14; c=a+b; print c}'

bash变量传进来

a=9; b=5
awk -v v1=$a -v v2=$b 'BEGIN{print v1/v2}'

======我是分割线=====

总行数:

awk 'END{print NR}' file1
'BEGIN{i=0}{i++}END{print i}'

=====我是分割线=====
模式匹配

'/root/{$3+=20; print $3}'
'/^root/{print $1}'
'!/root/{print $1}'
ifconfig -a | grep "^\w" | awk '!/lo/{print $1}'

'NR==2{print $1}'
'NR>=2&&NR<=5{print $1}'

'$1~/root/{print $1}' ~匹配 !~不匹配
'$1=="root"{print $1}'
'$3>=500 && $3<=505{print $1} /etc/passwd
'$3+$4>=100{print $1}'

'$1==v1{print $3}' v1是变量
'$0~v1{print $3}'
'$0~"^"v1{print $3}'

awk '/^root/' /etc/passwd 仅有模式匹配, 默认打印$0

=====我是分割线=====

'{if($1~/root/)print $0}'
'{if($1~/^root/)print $1; else print $2}'
'{if($1~/root/ && NR==1) print $1}'
'{if($1=="root") print $1; else if($1=="ftp") print $2; else print NR}'

next 读取下一行
exit 不再读取下一行, 跳到end语句块
'{if(NR>3) next; print $1}END{print NR}'
'{if(NR>3) exit; print $1}END{print NR}'

=====我是分割线=====

for
int()
'{printf "%.2f\n", $2/$3}'

=====我是分割线=====
执行shell命令:

a1 tom b1
a2 jerry b2
a3 lee b3
awk '{system("useradd "$2)}' file1

=====我是分割线=====

  • 本地变量
  • 环境变量
v1="ds.com"
export v1

PATH 仅对外部命令。
别名, 关键字(if for while), 函数, 内部命令, 外部命令

SHLVL
ps $$
PPID

  • 位置参数变量
$0 $1 ... ${10}
  • 预定义变量
$0
$#
$@ $* "$@" "$*"
for i相当于for i in "$@"
$?
$RANDOM

=====我是分割线=====

tar cjf abc.tar.bz2 "$@"
echo "运行 $0 脚本"
echo "共备份 $# 个文件"
echo "文件包括: $@"

=====我是分割线=====

for i in tom jerry mike
a="tom jerry mike"; for i in $a
for i in /boot/*
for i in *.mp3
for i in `seq -w 10`
for i in {1..10}
for i in `ls`
for i in `<file1`
for i in `cat file1`
for ((i=1; i<=5; i++))

=====我是分割线=====
循环中的break与continue

=====我是分割线=====

取位置参数
for i in "$@"
for ((i=1; i<=$#; i++)); do
    echo ${!i}
shift;

=====我是分割线=====
while后接的是一条命令
((i<=5))
取位置参数

while true; do
    read str
    if [ "$str" = "end" ]; then
        break;
    fi
done

======我是分割线=====
读文件内容

tom g1,g2,g3 /home/tom
jerry g1,g2 /home/jerry
lee g1 /home/lee
while read u g h; do 
    echo $g | cut -d, -f1
done <file1或cat file1 | while

=====我是分割线=====
无限循环、读文件内容用while, 其它均用for

=====我是分割线=====
until
与while逻辑相反

=====我是分割线=====
case
参考/etc/init.d/vsftpd等

=====我是分割线=====

PS3="input :"
select i in a b c; do
    if [ "$REPLY" = "tom" ];
        bash bind.sh
    fi
done

=====我是分割线=====
function 返回值 给函数传参数 local
/etc/init.d/functions

# bash standard lib function

=====我是分割线=====

# function: 判断偶数
# para: 位置参数
# return: 0 or 1
# usage: even 3

=====我是分割线=====

even() {
    local i=${1: -1}
    case "$i" in
        [02468])  return 0;;
        *)        return 1;;
    esac
}

=====我是分割线=====

find . -nouser
find / -size +200M
find . -maxdepth 1 -name "*.conf"
find . -perm 600

=====我是分割线=====
grep: global search regular expression(RE) and print out the line

grep -n --color
grep -c
grep -v "^\s*$"
grep -wq
grep -ro "root" dir1
grep -Ei
grep -f file1 file2
grep -x "abc" file1

=====我是分割线=====
seq

=====我是分割线=====
tr
单字符处理工具, 而不是字符串处理工具

cat file1 | tr "abc" "xyz"
a都替换成x, b都替换成y, c都替换成z
并不是将字符串abc替换成字符串xyz

tr "a-z" "A-Z" <file1
echo $PATH | tr ":" "\n"

cat file1 | tr -d "abc"
所有的a、b、c字符都会被删除, 并不是删除abc字符串

echo "123abcXYZ" | tr -d "a-zA-Z" 
cat file1 | tr -d "\n\t"
echo "a b c" | tr –d " "

echo "aaabbbccc" | tr -s "a-zA-Z"
echo "a b  c   d    e" | tr -s " "

删除windows文件中的^M字符(回车符\r)
cat file1 | tr -d "\r"
man bash  | col -b >file1

=====我是分割线=====
sort默认字段分隔符为空白(与awk一样)
sort -t: /etc/passwd 默认以第1个字段排序
sort -t: -k3nr /etc/passwd

=====我是分割线=====
先sort再uniq

=====我是分割线=====
cut默认字段分隔符为tab

cut -d: -f1,3,5
echo "abcdef" | cut -c2

=====我是分割线=====

find -name "in*" | xargs rm -f
find -name "in*" | xargs -I{} chown tom:tom {}
find -name "in*" | xargs -I{} cp {} /tmp/{}.bak

=====我是分割线=====

trap 'ls –l; date; cal; fun1' 2
sleep 60
ctrl + c, 触发2

trap '' 2 不做什么
trap 2 复原

=====我是分割线=====

curl -o小写 a.html http://www.sohu.com
curl -O大写 http://images.sohu.com/bill/s2013/MKT/shipin/huafeihua/450105-0828.jpg
curl -O ftp://10.0.40.1/pub/fstab
curl -T file1 ftp://tom:aixocm@10.0.1.254:21/dir1/ 注意最后/

=====我是分割线=====
array
0号元素, 1号元素, 2号元素, 目前只支持一维数组。
不要求每个元素的数据类型一致, 实际上均为string。

names=(tom jerry mike)
names=([0]=tom [1]=jerry [3]=mike [5]=lee john)

names[0]=tom
names[1]=jerry
names[2]=lee

names[x++]=tom
names[x++]=jerry
names[x++]=mike

for i in "${names[@]}"
for ((i=0; i<${#names[@]}; i++)); do
    echo ${names[i]}

while read a b c; do
    arr[x++]=$a
done <file1

a=(`for i in {0..9}; do echo $RANDOM; done`)
for i in `seq 10`; do
    arr[x++]=$RANDOM
done
arr=(`route -n | grep -i "ug"`)

v1="abc def hij"
v2=($v1)

echo ${!names[@]}
unset names; unset names[2]

=====我是分割线=====
字符串长度

a="xyz123"
${#a}     

字符所在位置

expr index $a "z"

截取

${a:4}
${a:4:3}
${a: -1}同${a:(-1)}

a="file1.tar.gz"
${a#*.}; ${a##*.}
%

替换

${a/xyz/def}
${a//xyz/def}

shell不需要启动一个单独的进程来运行内部命令, 性能较高, 由bash自带。
shell需要创建(fork)和执行(exec)一个新的子进程来运行外部命令。

=====我是分割线=====
bash中的符号

* ?

"" "*" "ds's keji" "abc `date` def" "abc $PATH def" "!if" find -name "*.sh"

''

\ \* ds\'s\ keji

``与$()  $()可以嵌套

; 命令结束符

& 在后台运行, 在子shell中运行

() 一组命令, 在子shell中执行 array元素

{} 一组命令, 在当前shell执行 touch a{1,2,3,4,5} touch a{1..10..2} ${var1}23

a=5 echo {1..$a} eval echo {1..$a}

((a=10*2)) ((a == 10 / 2))

[]  有且仅有1个 ls test[^0-9].sh, ^取反 数组下标 测试, 同test


[[ "$a" == *“abc”* ]]


| 管道两边的命令均在子shell中执行, 在子shell中定义的变量不能传递出来到父shell

>  >>  <  << &> &>> stdin 文件描述符0, 默认是键盘 stdout 1, 默认是终端显示器 stderr 2, 显示器

tr "a-z" "A-Z" <file1 gunzip <a1.gz >a2 mysql ds <a.sql    


$ 取变量的值
# 注释


! 执行历史命令 取反 间接取变量的值

echo ${#a} echo ${#a[@]} echo ${!a[@]}


空格、制表符、换行符均当作空白 

&&  || if [ $a -eq 0 ] && [ $b -eq 0 ]

=====我是分割线=====
执行shell脚本的3种方法

G
chmod +x test.sh

  • ./test.sh 在子shell, 常用
  • bash -xv test.sh 在子shell, 一般用来调试脚本
  • source test.sh或.命令, 在当前shell

=====我是分割线=====
bash的环境变量配置文件

login shell, 输入用户名与密码

执行的脚本文件依次如下:

  • /etc/profile
  • /etc/profile.d/*.sh
  • ~/.bash_profile
  • ~/.bashrc
  • /etc/bashrc 注意看最后那个if

non login shell
登录系统之后启动的shell
bash命令、在图形中打开终端(gnome-terminal)、su

执行的脚本文件依次如下:

  • ~/.bashrc
  • /etc/bashrc
  • /etc/profile.d/*.sh

退出登录shell时, 执行:

  • ~/.bash_logout

=====我是分割线=====
什么是shell编程
shell的作用: 是一个软件, 一个cli, 一门解释型的面向过程的程序设计语言.

shell如何解析一个完整的命令行? 命令行的处理过程如下:
1. 历史命令替换
2. 命令行拆分为token(单词)(以空格或tab隔开, 即以空白隔开)
3. 历史更新
4. 处理引用
5. 定义别名替换和函数
6. 建立重定向、后台、管道
7. 变量替换($USER、$NUM等)
8. 命令替换(echo “abc `date` def”)
9. 文件名替换(*.conf -> a.conf b.conf)
10. 程序执行(内部命令、外部命令、shell脚本等)

一个命令行在执行之前, shell先将其参数进行替换(解析、扩展)
如将变量替换、命令替换、文件名替换, 最后才执行命令
对二进制程序它解析不了, 它解析的是程序执行之前命令行中的参数

=====我是分割线=====
方法1
首选项->远程桌面(vino)

方法2
tigervnc-server
vncserver :1
service vncserver status
vncserver -kill :1

tigervnc
vncviewer 192.168.0.253:1 -shared -fullscreen -viewonly

=====我是分割线=====
shell如何执行命令
内部命令是shell解释程序内建的, 由bash直接执行, 不需要派生新的进程。

外部命令(external command or disk command)
二进制可执行文件, 需要由磁盘装入内存执行, 会派生新的进程。
bash会fork自身的一个拷贝
然后用exec系列函数来执行外部命令
然后外部命令就取代了先前fork的子shell

shell脚本(script)
shell解释程序会fork+exec执行这个脚本
在exec调用中内核会检查脚本的第一行(如#!/bin/sh)
找到用来执行脚本的解释程序, 然后装入这个解释程序, 由它解释执行脚本程序

=====我是分割线=====
shell脚本是否作为单独的一个进程执行。
不是, shell脚本本身不能作为一个进程。
shell脚本由一个shell解释程序来解释运行其中的命令
这个shell解释程序是单独的一个进程, 脚本中的外部命令也都作为独立进程依次被运行。
这也就是为什么ps不能找到正在运行的脚本的名字的原因了。

=====我是分割线=====
Korn shell的较新的版本(ksh93以后)比较特殊
管道最后一级的命令是在当前shell执行的
这是一个feature而非bug, 在POSIX标准中也是允许的
这样就使下面的命令结构成为可能
cmd | read var
由于read var在当前shell中执行, 所以当前shell中就有var变量

但不是所有的shell都是这样实现的
如开源的pdksh就是在子shell中执行管道的每一级命令
(bash/pdksh/ash/dash均是在子shell中执行)

Korn shell对管道的处理还有一个特殊的地方
就是管道如果在后台执行的话, 管道前面的命令会由最后一级的命令派生
而不是由当前shell派生出来, 据说Bourne shell也有这个特点
但是他们的开源模仿者pdksh和ash却不是这样处理的

=====我是分割线=====
rsync /dir1/* /dir2/ 将/dir1下的文件同步到/dir2中
将字体文件.ttf文件copy入/usr/share/fonts/chinese/TrueType/下

当linux的字符编码不是utf-8而是gb2312时,smb挂windows分区中文文件名乱码。

mount -t cifs //192.168.8.6/e$ /mnt -o username=administrator%password -o iocharset=gb2312即可

fuser -vm /dir1 谁正在访问/dir1
fuser -km /dir1再umount就没有问题了

=====我是分割线=====
系统状态信息:

iostat
uptime
w
vmstat
top
free -m
lsof -i:http
ps aux
dmesg
pgrep -x vsftpd
tty

cat /proc/cpuinfo
free
uptime
netstat -s
装sysstat软件包
iostat

=====我是分割线=====
Linux中清空本机本地的dns缓存(作用同win下的ipconfig /flushdns)
rpm -q nscd(默认有)
/etc/rc.d/init.d/nscd restart
service nscd restart

gunzip zic.8.gz; man ./zic.8

/etc/sudoers(visudo)
tom rhel5(root) /usr/bin/passwd
普通用户 主机名 身份 可以执行的命令

hdparm -t /dev/sda
vim /etc/fstab->,noatime 禁用日志写入,mount / -o remount就生效了。

与某功能相关的命令:
man -k nfs
man -k lvm
man -k copy
man -k raid
whatis的作用:这条命令是做什么的,如:whatis mdadm

=====我是分割线=====
某些发行版会在后台运行一个域名解析缓存服务,当然,也有发行版没有这个服务。如果您的Ubuntu后台有这个程序,那么您可以用重新启动 nscd服务的方式来清空缓存。
为啥要清空缓存?

  • 大多数的 DNS 客户端会把域名解析的结果缓存到本地, 这样可以提升对于同一个地址的访问速度。当您打开一个单页面的时候,通常会有多次对同一个域名 的访问请求。基本上每个文件、图片、样式表……这 些都是在同一个页面内部的对同一个域名的DNS 解 析请求。
  • 所以如果您已经在本地缓存了不正确的 DNS 条目,那么您需要清空您的缓存来使 DNS 客户端提出新的DNS 请求并更新解析结果。当然,您也可以等缓存的 DNS 条目过期以后让系统自动冲掉该条目……这通常需要24个小时。
  • 在 ubuntu 中冲掉 DNS 缓存的方式是重新启动 nscd 守护程序。

安装 nscd 的方式是在命令行中运行这条命令:
sudo aptitude install nscd
在Ubuntu中清 DNS 缓存的命令是:
sudo /etc/init.d/nscd restart

注释多行:

:.,$s/^/#/
:.,+5s/^#//

ls -l modify time
ls -lc ctime, i节点被修改, chmod或chown
ls -lu access time, cat或more
stat

=====我是分割线=====
取最后一个字符

echo ${a: -1}
echo $a | rev | cut -c1

看文件的第几行

sed -n '5p' file1

awk 'NR==5' file1

head -5 file1 | tail -1

=====我是分割线=====

$MAILCHECK

LANG=C C即ascii, 或LANG=也可, 自动使用英文
vim /etc/sysconfig/i18n 
echo $LANG
LANG="en_US.UTF-8"
LANG="zh_CN.UTF-8"

man bash | col -b >file1

mount --bind /mnt /var/ftp/rhel6.4

=====我是分割线=====

linux下phpWeb页面调用命令行
以什么身份执行的shell命令? apache用户

system("ls /etc"); 单双引号均可
system("mkdir /abc");

system("ls; pwd; date", $re);
echo $re;
返回值[0, 255], 0为命令通过, 非0则是错误号码

system("iptables -nL"); 执行不了
system("ls /root"); 执行不了
chmod +s /sbin/iptables /bin/ls
posted @ 2017-10-24 14:45  斯言甚善  阅读(267)  评论(0编辑  收藏  举报