shell脚本常用命令

Shell 脚本

Shell 脚本(shell script),是一种为 shell 编写的脚本程序。

业界所说的 shell 通常都是指 shell 脚本,但读者朋友要知道,shell 和 shell script 是两个不同的概念。

由于习惯的原因,简洁起见,本文出现的 “shell编程” 都是指 shell 脚本编程,不是指开发 shell 自身。

常见基础命令:

单引 双引 反引用[] [[]]
将命令的输出读入一个变量中,可以将它放入双引号中,即可保留空格和换行符(\n)

out=$(cat text.txt)

输出1 2 3

out="$(cat text.txt)"

输出:

1

2

3
逻辑运算符:

-gt 大于

-lt 小于

-ge 大于等于

-le 小于等于

逻辑与-a

[ $var1 -eq 0 -a $var2 -gt 2 ]

逻辑或

[ $var1 -eq 0 -o $var2 -gt 2 ]

[ condition ] && action 等价于if…fi

if [ “$LOOK_OUT” -gt “85” ]

if [ -e /home/slynux ]; then

fi

-----------------[[]]一般用于字符串比较

if [[ -n $str1 ]] && [[ -z $str2 ]] ;

then

commands;

fi

========================

1、字符串判断

str1 = str2      当两个串有相同内容、长度时为真
str1 != str2      当串str1和str2不等时为真
-n str1        当串的长度大于0时为真(串非空) if [[ -n $1 ]]
-z str1        当串的长度为0时为真(空串)
str1         当串str1为非空时为真

2、数字的判断

int1 -eq int2    两数相等为真
int1 -ne int2    两数不等为真
int1 -gt int2    int1大于int2为真
int1 -ge int2    int1大于等于int2为真
int1 -lt int2    int1小于int2为真
int1 -le int2    int1小于等于int2为真

3 目录文件的判断(if [ ])

-r file     用户可读为真
-w file     用户可写为真
-x file     用户可执行为真
-f file     文件为正规文件为真
-d file     文件为目录为真
-c file     文件为字符特殊文件为真
-b file     文件为块特殊文件为真
-s file     文件大小非0时为真
-t file     当文件描述符(默认为1)指定的设备为终端时为真

3、复杂逻辑判断

-a         与
-o        或
!        非

下面是一些使用实例:

#!/bin/sh
myPath="/var/log/httpd/"
myFile="/var /log/httpd/access.log"

#这里的-x 参数判断 m y P a t h 是 否 存 在 并 且 是 否 具 有 可 执 行 权 限 i f [ ! − x " myPath是否存在并且是否具有可执行权限 if [ ! -x " myPathif[!x"myPath"]; then
mkdir “$myPath”
fi

#这里的-d 参数判断 m y P a t h 是 否 存 在 i f [ ! − d " myPath是否存在 if [ ! -d " myPathif[!d"myPath"]; then
mkdir “$myPath”
fi

#这里的-f参数判断 m y F i l e 是 否 存 在 i f [ ! − f " myFile是否存在 if [ ! -f " myFileif[!f"myFile" ]; then
touch “$myFile”
fi

#其他参数还有-n,-n是判断一个变量是否是否有值
if [ ! -n “ m y V a r " ] ; t h e n e c h o " myVar" ]; then echo " myVar"];thenecho"myVar is empty”
exit 0
fi

#两个变量判断是否相等
if [ “ v a r 1 " = = " var1" == " var1"=="var2” ]; then
echo ‘$var1 eq v a r 2 ′ e l s e e c h o ′ var2' else echo ' var2elseechovar1 not eq $var2’
fi

-----------------获取名称.扩展名

file_jpg=“sample.jpg”

name=${file_jpg%.*}

输出sample

file_jpg=“sample.jpg”

extension=${file_jpg#*.}

输出jpg

------------------ time 计算命令执行时间

time command

--------------- 重定向

0 stdin标准输入

1 stdout标准输出

2 stderr标准错误

文件打开模式:

等同于1> 截断模式

等同于1>> 追加模式

<用于从文件中读取至stdin 只读模式

ls + 2> out.txt

stdout不会有任何输出,因为错误已经重定向到out.txt中了

可以将stderr单独重定向到一个文件,将stdout重定向到另一个文件:

cmd 2>stderr.txt 1>stdout.txt

将stderr转换成stdout,使得stderr和stdout都被重定向到同一个文件:

cmd 2>&1 output.txt

或者

cmd &> output.txt

将stderr输出丢弃

some_command 2> /dev/null

将文件重定向到命令

cmd < file

向log文件中写入头部数据

#!/bin/bash

cat

LOG FILE HEADER

this is a test log file

EOF

-----------------------/dev/null 2>&1

*/1 * * * * root /usr/local/php/bin/php /var/w.php > /dev/null 2>&1

crontab内容:50 18 5-30 * * /script/myscript.sh 1> /dev/null 2>&1
其中 1> /dev/null 2>&1是什么意思??
dev/null 为系统垃圾箱
&为后台运行
但是 myscript 后面的1 和 /null后面的2 还有 &后面的1是什么意思?
1代表标准输出,2代表错误信息输出.
1>/dev/null 就是指将标准输出定向到空设备,
2>&1,的意思是将错误输出定向到和1一样的输出设备,也同样是空.

换句话说,就是不显示该程序执行过程中的任何信息

cmd >a 2>a 和 cmd >a 2>&1 为什么不同?
cmd >a 2>a :stdout和stderr都直接送往文件 a ,a文件会被打开两遍 ,由此导致stdout和stderr互相覆盖。
cmd >a 2>&1 :stdout直接送往文件a ,stderr是继承了FD1的管道之后,再被送往文件a 。a文件只被打开一遍,就是FD1将其打开
他们的不同点在于:
cmd >a 2>a 相当于使用了FD1、FD2两个互相竞争使用文件 a 的管道;
而cmd >a 2>&1 只使用了一个管道FD1, 但已经包括了stdout和stderr。
从IO效率上来讲,cmd >a 2>&1的效率更高。

----------------- 算数运算 let expr

let 可以直接执行基本的算数操作

no1=4

no2=5

let result=no1+no2

echo $result

let no1++

let no1+=6

操作符[] ,expr 和let命令类似

result=$[ no1 + no2 ]

result=$[ $no1 + $no2 ]

result=expr 3 + 4

result=$(expr $no1 + 5)

---------------- 浮点运算 bc

#echo “4 * 0.56” | bc

2.24

-----------------获得字符串长度

var=123456

echo ${#var}

-----------------环境变量$PATH和export

echo $PATH

PATH通常定义在/etc/environment或/etc/profile或~/.bashrc中

export命令用来设置环境变量;

添加新的路径:

export PATH="$PATH:/home/user/bin"

或者

PATH="$PATH:/home/user/bin"

export PATH

其它环境变量:HOME,PWD,USER,UID,SHELL

查看进程相关的环境变量:

cat /proc/$PID/environ

----------------- printf 格式化输出

printf “%-5s %-10s %-4s\n” No Name Mark

printf “%-5s %-10s %-4.2f\n” 1 James 91.32

输出为:

No Name Mark

1 James 91.32

%-5s 指明了一个格式为左对齐且宽度为5的字符串替代(- 表示左对齐)

-4.2f 表示对浮点数的处理格式

-------------- 读取命令返回值$?

cmd;

echo $?;

-------------------------shell 调试

#!/bin/bash -xv 不用任何其他选项就可以启用调试功能了

sh -n sh16.sh 不执行script,仅查询语法

sh -x sh16.sh 将script执行过程全部列出来

需要给变量赋值时,可以这么写:
变量名=值
要取用一个变量的值,只需在变量名前面加一个$

a=“hello world”
echo “A is:” $a

//if 注意空格

a=$1

if [[ $a -eq 2 ]] ;then

echo “1”

else

echo “2”

fi

if [[ $a = gjslint ]] ;then

echo “1”

exit 0

else

echo “2”

fi

exit 0

===================== 调用php的sh

#!/bin/bash

if [[ $0 = /* ]]

then

curfile="$0"

else

curfile=" P W D / PWD/ PWD/{0#./}"

fi

#得到curfile 为/usr/local/shell/automation/autoupdate_host.sh

php_path=dirname $curfile

#得到php_path为/usr/local/shell/automation

PHP="/usr/local/php/bin/php -q "

PROGRAM="${php_path}/clear_his.php"

#echo $PHP $PROGRAM &

$PHP $PROGRAM &

====================== [和[[有什么不同

$ type [
[ is a shell builtin
$ type [[
[[ is a shell keyword

也就是说[处理里面的字串是当作参数来处理的,而[[对待其中的字串是当作表达式来处理的
那么当作参数和表达式有什么不同呢?

表达式中不会有wordsplitting 或者glob expansion,而参数处理会有

$ ls
file file 1 #注意是2个文件(file 和file 1)
$ (foo=“file 1”;[[ -f KaTeX parse error: Expected 'EOF', got '&' at position 7: foo ]]&̲&echo "foo is a file")
file 1 is a file

]$ (foo=“file 1”;[ -f KaTeX parse error: Expected 'EOF', got '&' at position 6: foo ]&̲&echo "foo is a file") # 这里file 1被分成2个word,所以出错
bash: [: file: binary operator expected

再来看看glob expansion

$ touch '
$ (foo="
";[ -f KaTeX parse error: Expected 'EOF', got '&' at position 6: foo ]&̲&echo "foo is a file") #为什么显示too many arguments,因为 被扩展为所有目录下的文件
bash: [: too many arguments
$ (foo="
";[[ -f KaTeX parse error: Expected 'EOF', got '&' at position 7: foo ]]&̲&echo "foo is a file") # *被当成普通字符了

  • is a file

参数传递中<和>会被解析成重定向符号,所以必须转义掉

$ ([ “s” < “l” ]&&echo yes) #错误使用
bash: l: No such file or directory

$ ([ “s” > “l” ] &&echo yes) #正确使用
yes

$ ([[ “s” > “l” ]] &&echo yes) #而在表达式中比较符号不会被当作重定向符号
yes

参数传递中小括号会被分割成token,而在表达式中则会被解析成运算顺序

$ ([ “s” > “l” -a ( file “l” > “a” -o “l” > “p” ) ]&&echo yes) #(和)必须被转义,以避免参数解析中的不正确分词
bash: syntax error near unexpected token `(’

$ ([ “s” > “l” -a “l”“a"−o"l”“p” ] &&echo yes)
yes

$ ([[ “s” > “l” && ( “l” > “a” || “l” > “p” ) ]] &&echo yes; ) #而表达式则不需要考虑这个
yes

================ shell判断文件是否存在

shell判断文件,目录是否存在或者具有权限
#!/bin/sh

myPath="/var/log/httpd/"
myFile="/var /log/httpd/access.log"

这里的-x 参数判断$myPath是否存在并且是否具有可执行权限

if [ ! -x “ m y P a t h " ] ; t h e n m k d i r " myPath"]; then mkdir " myPath"];thenmkdir"myPath”
fi

这里的-d 参数判断$myPath是否存在

if [ ! -d “ m y P a t h " ] ; t h e n m k d i r " myPath"]; then mkdir " myPath"];thenmkdir"myPath”
fi

这里的-f参数判断$myFile是否存在

if [ ! -f “ m y F i l e " ] ; t h e n t o u c h " myFile" ]; then touch " myFile"];thentouch"myFile”
fi

其他参数还有-n,-n是判断一个变量是否是否有值

if [ ! -n “ m y V a r " ] ; t h e n e c h o " myVar" ]; then echo " myVar"];thenecho"myVar is empty”
exit 0
fi

两个变量判断是否相等

if [ “ v a r 1 " = " var1" = " var1"="var2” ]; then
echo ‘$var1 eq v a r 2 ′ e l s e e c h o ′ var2' else echo ' var2elseechovar1 not eq $var2’
fi

-f 和-e的区别
Conditional Logic on Files

-a file exists.
-b file exists and is a block special file.
-c file exists and is a character special file.
-d file exists and is a directory.
-e file exists (just the same as -a).
-f file exists and is a regular file.
-g file exists and has its setgid(2) bit set.
-G file exists and has the same group ID as this process.
-k file exists and has its sticky bit set.
-L file exists and is a symbolic link.
-n string length is not zero.
-o Named option is set on.
-O file exists and is owned by the user ID of this process.
-p file exists and is a first in, first out (FIFO) special file or named pipe.
-r file exists and is readable by the current process.
-s file exists and has a size greater than zero.
-S file exists and is a socket.
-t file descriptor number fildes is open and associated with aterminal device.
-u file exists and has its setuid(2) bit set.
-w file exists and is writable by the current process.
-x file exists and is executable by the current process.
-z string length is zero.

==================bash中的特殊符号

  • 万用字符,代表一个或多个字符(或数字)

? 万用字符,代表一个字母

| 分隔两个管线命令的界定;

; 连续性命令的界定(注意!与管线命令并不相同)
使用者的家目录

$ 亦即是变量之前需要加的变量取代值

& 将指令变成背景下工作

! 逻辑运算意义上的『非』 not 的意思!

/ 路径分隔的符号

, >> 输出导向,分别是『取代』与『累加』

’ 单引号,不具有变量置换的功能

" 具有变量置换的功能!

两个『 ` 』中间为可以先执行的指令!

( ) 在中间为子 shell 的起始与结束

[ ] 在中间为字符的组合

{ } 在中间为命令区块的组合!

exit 1:退出整个程序

--------------------dirname

dirname /home/bin/abc
得到/home/bin

------------------------- 循环读取每行 :
all_corp=sql.txt
cat $all_corp | while read line
do
echo $line
done

-----------------------整数比较

-eq 等于,如:if [ “ a " − e q " a" -eq " a"eq"b” ]
-ne 不等于,如:if [ “ a " − n e " a" -ne " a"ne"b” ]
-gt 大于,如:if [ “ a " − g t " a" -gt " a"gt"b” ]
-ge 大于等于,如:if [ “ a " − g e " a" -ge " a"ge"b” ]
-lt 小于,如:if [ “ a " − l t " a" -lt " a"lt"b” ]
-le 小于等于,如:if [ “ a " − l e " a" -le " a"le"b” ]

if [ $counter -gt 1 ]; then

fi

< 小于(需要双括号),如:((“ a " < " a" < " a"<"b”))
<= 小于等于(需要双括号),如:((“ a " < = " a" <= " a"<="b”))

大于(需要双括号),如:((“ a " > " a" > " a">"b”))
= 大于等于(需要双括号),如:((“ a " > = " a" >= " a">="b”))

---------------------------字符串比较
= 等于,如:if [ “ a " = " a" = " a"="b” ]
== 等于,如:if [ “ a " = = " a" == " a"=="b” ],与=等价
注意:==的功能在[[]]和[]中的行为是不同的,如下:
1 [[ KaTeX parse error: Expected 'EOF', got '#' at position 12: a == z* ]] #̲ 如果a以"z"开头(模式匹配 )那么将为true
2 [ KaTeX parse error: Expected 'EOF', got '#' at position 13: a == "z*" ] #̲ 如果a等于z*(字符匹配 ),那么结果为true
3
4 [ KaTeX parse error: Expected 'EOF', got '#' at position 11: a == z* ] #̲ File globbing …a" == “z*” ] # 如果 a 等 于 z ∗ ( 字 符 匹 配 ) , 那 么 结 果 为 t r u e 一 点 解 释 , 关 于 F i l e g l o b b i n g 是 一 种 关 于 文 件 的 速 记 法 , 比 如 " ∗ . c " 就 是 , 再 如   也 是 . 但 是 f i l e g l o b b i n g 并 不 是 严 格 的 正 则 表 达 式 , 虽 然 绝 大 多 数 情 况 下 结 构 比 较 像 . ! = 不 等 于 , 如 : i f [ " a等于z*(字符匹配),那么结果为true 一点解释,关于File globbing是一种关于文件的速记法,比如"*.c"就是,再如~也是. 但是file globbing并不是严格的正则表达式,虽然绝大多数情况下结构比较像. != 不等于,如:if [ " az(),true,Fileglobbing,".c", .fileglobbing,.!=,:if["a" != “ b " ] 这 个 操 作 符 将 在 [ [ ] ] 结 构 中 使 用 模 式 匹 配 . < 小 于 , 在 A S C I I 字 母 顺 序 下 . 如 : i f [ [ " b" ] 这个操作符将在[[]]结构中使用模式匹配. < 小于,在ASCII字母顺序下.如: if [[ " b"][[]]使.<,ASCII.:if[["a” < “ b " ] ] i f [ " b" ]] if [ " b"]]if["a” < “$b” ]
注意:在[]结构中"<"需要被转义.

大于,在ASCII字母顺序下.如:
if [[ “ a " > " a" > " a">"b” ]]
if [ “ a "   " a" \> " a""b” ]
注意:在[]结构中">“需要被转义.
具体参考Example 26-11来查看这个操作符应用的例子.
-z 字符串为"null”.就是长度为0.
-n 字符串不为"null"
注意:
使用-n在[]结构中测试必须要用"“把变量引起来.使用一个未被”“的字符串来使用! -z
或者就是未用”“引用的字符串本身,放到[]结构中。虽然一般情况下可
以工作,但这是不安全的.习惯于使用”"来测试字符串是一种好习惯.

awk ‘{print $2}’ class.txt | grep ‘1’ > res

iptables 配置文件目录 /etc/sysconfig/iptables

1.别名 alias,存放位置 $HOME/.bashrc
alias ll=‘ls -lh’
2.print=helloworld echo ${print}
3.变量:内存中一块存储单元
本地变量:登陆登出生命周期内有效,只限制于本用户
变量名=变量值
set 查看
LOCAL=“TEST”
echo $LOCAL
设置变量名为只读,不能在更改,同是也不能在恢复:readonly 变量名,不能删除。

环境变量:系统变量,用于所有用户,只有环境变量才能用于所有的子进程中,本地变量不可以。
存放于/etc/profile .bash_profile
export 变量名=变量值
env或者export查看
unset 变量名 删除

变量替换:用变量的值替换变量的名
print=helloworld
echo ${print}
echo f i l e 1 + {file1}+ file1{file2}

--------------------位置变量:$0 $1…$9
$0:脚本的名字
$1:脚本的第一变量
$2:脚本的第二变量
向脚本中使用位置参数:./test.sh a b c

向系统命令传递参数
find /root/ -name $1 -print
./test.sh aa

标准变量:bash默认的,可以在/etc/profile中定义
EXINIT
HOME
IFS:设置分隔符,默认为空格 IFS=":"SHE
LOGNAME
MAIL 默认邮箱位置
MAILPATH多个邮箱时可以设置
TERM 显示终端类型
PS1 当前shell目录格式PS1=“WANGJIAN:”
ps2 >
pwd显示当前路径 SHELL 显示当前shell
MANPATH TERMINFO

----------------------------------------------------------特殊变量
$# 变量的个数 $* 显示脚本全部参数(参数列表)

$$脚本运行的当前id号
$?显示前一个命令的运行状态

$!后台运行的最后一个进程id号
#!/bin/bash
echo “tesh.sh”
echo “this is first variable locate:$1”
echo “this is second variable locate:$2”
echo “this is third variable locate: 3 " s h i f t e c h o " c o u n t : 3" shift echo "count: 3"shiftecho"count:#”
echo “all list: ∗ " e c h o " p i d : *" echo "pid: "echo"pid: " e c h o " s t a t u s : " echo "status: "echo"status:?”

./tesh.sh a b c

declare :设置或显示变量 -f只显示函数名
export:创建环境变量 -p显示所有环境变量
readonly:设置只读变量,不能修改删除
unset:取消变量的定义。-f 删除只读变量
shift:输入的位置变量改变位置 shift 表位置上移一个位置,shift 2 表上移动两个位置
双引号"":引用字符或字符串除$ \ 单引号\'\':直接引用为字符或字符串 反引号``: 作为系统命令执行 echoecho wangjian` wangjian
反斜杆:转义特殊字符(KaTeX parse error: Expected 'EOF', got '&' at position 26: …算符:~取反 << >>移位 &̲与(同1为1,否0) |或(有…[]:表示对其中的表达式求值 echo $[2+8] echo $[3&4] $[]等价于(())
[base#n] n(base>n)表示基数从2到36的任何基数 echo [10#8+1] 结果为9
let a+=3 a=a+3
表达式优先级别[] *= || && | ^ & ==
shell 的输入与输出
echo
-e 解析转义字符 echo -e “this is a bag \n\n\n”
-n 回车不换行,默认换行 echo -n “this is a cat”
转义字符(\c回车不换行 \f禁止 \t跳格相当tab \n回车换行)

read:可以从键盘或文件的某一行文本中读入信息,并将其赋给一个变量。
read varible1 varible2
如果只指定了一个变量,那么read将会把所有的输入赋给改变量,直至遇到文件结束或回车。如果多个变量,就依次赋给。shell用空格作为变量之间的分隔符。
echo -n “first name:”
read firstname
echo -n “last name:”
read lastname
echo -e "your first name :KaTeX parse error: Undefined control sequence: \n at position 12: {firstname}\̲n̲" echo -e "your…{lastname}\n "

read -t 5 variable 5秒钟超时
read -p "Please enter your Username: " user -p prompt 提示语
[root@ceshiji ~]#Please enter your Username:

read -s -p "Please enter your Password: " pass -s charaters are not echoed. 字符不回显示。指输入之后,不在回显


  1. 0-9. ↩︎

你可能感兴趣的:(shell)