您的位置:首页 > 运维架构 > Shell

很全的shell知识总结宝典

2017-10-24 14:45 127 查看
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出现的次数为3次
echo "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}" --colo
4000
r


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

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: