1.脚本编写和执行
编写shell脚本:
[root@hadoop000 shell]# vi helloworld.sh
#!/bin/bash
echo "hello world"
直接执行会报权限错误:
[root@hadoop000 shell]# ./helloworld.sh
-bash: ./helloworld.sh: Permission denied
[root@hadoop000 shell]# /opt/shell/helloworld.sh
-bash: /opt/shell/helloworld.sh: Permission denied
输入文件名,会从PATH中找命令,没有就会报错,所以会把文件名当成命令而不是执行shell:
[root@hadoop000 shell]# helloworld.sh
-bash: helloworld.sh: command not found
[root@hadoop000 shell]# pwd
/opt/shell
[root@hadoop000 shell]# echo $PATH
/opt/software/hadoop-2.8.1/bin:/usr/local/protobuf/bin:/opt/software/findbugs-1.3.9/bin:/opt/software/apache-maven-3.3.9/bin:/usr/java/jdk1.8.0_45/bin:/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
2.赋给x权限:
赋权限一般是给所属用户赋权限,但有的是直接给所属用户组赋权限。
[root@hadoop000 shell]# ll
total 4
-rw-r--r--. 1 root root 40 Jun 12 21:11 helloworld.sh
全部加上x权限:chmod +x helloworld.sh
chmod g+x helloworld.sh
[root@hadoop000 shell]# chmod 654 helloworld.sh
[root@hadoop000 shell]# ll
total 4
-rw-r-xr--. 1 root root 40 Jun 12 21:11 helloworld.sh
[root@hadoop000 shell]# ./helloworld.sh
hello world
3.调试
[root@hadoop000 shell]# vi helloworld.sh
#!/bin/bash -x
echo "www.ruozedata.com"
在文件内的第一行加上-x,在执行的时候就会是调试模式,在执行的命令后面加-x也是调试模式。
4 sh命令
sh命令对于没有第一行标识的shell文件也能执行,没有x权限的也可以执行。bash和sh类似,linux中sh是链接到bash上的,所以sh与bash在功能上是没有区别的。
[root@hadoop000 shell]# sh -x helloworld.sh
+ echo hello world
hello world
5.变量定义及引用
[root@hadoop000 shell]# vi variable.sh
#!/bin/bash
rz="variable"
date=`date`
echo $rz
echo $date
静态:
k="v"
k='v'
k=v
动态:
k=`v` :动态的要加上tab键上面的那个字符
=前后不能有空格
引用:
$k
${k}
echo $klmn :会在该打印的地方出现空白行
echo ${k}lmn :会打印出来vlmn
总结:
1.=前后不能有空格
2.字符串建议双引号
3.引用变量加上{}
6.传递参数
[root@hadoop000 shell]# vi parameter.sh
#!/bin/bash
echo $1
echo $2
echo "个数:$#"
echo "传递参数作为1个字符串显示: $*"
echo "PID: $$"
[root@hadoop000 shell]# sh parameter.sh a b
a
b
个数:2
传递参数作为1个字符串显示: a b
PID: 2647
[root@hadoop000 shell]# sh parameter.sh "a b"
a b
个数:1
传递参数作为1个字符串显示: a b
PID: 2649
[root@hadoop000 shell]#
PID能够标识运行的进程,如果使用ps -ef|grep的话,得到的可能是别人的进程的pid,容易杀错。
7.数组 (一维)
[root@hadoop000 shell]# vi array.sh
#!/bin/bash
arr=(a b c d e )
echo ${arr[*]}
echo ${arr[@]}
echo ${arr[4]}
echo ${#arr[@]}
[root@hadoop000 shell]# sh array.sh
a b c d e
a b c d e
e
5
[root@hadoop000 shell]#
注:这里的* 也可以用@表示
8.if判断
[root@hadoop000 shell]# vi if.sh
#!/bin/bash
a="abc"
b="def"
if [ $a == $b ];then
echo "=="
else
echo "!="
fi
[root@hadoop000 shell]# sh if.sh
!=
[root@hadoop000 shell]# sh -x if.sh
+ a=abc
+ b=def
+ '[' abc == def ']'
+ echo '!='
!=
另外一种then放的位置:
if [ "$a" == "$b" ]
then
注:在引用字符串的时候,最好也加上双引号"$a"。
[root@hadoop000 shell]# vi if.sh
#!/bin/bash
a="ccc"
b="def"
if [ "$a" == "$b" ]
then
echo "=="
elif [ "$a" == "ccc" ]
then
echo "ccc"
else
echo "!="
fi
[root@hadoop000 shell]# sh -x if.sh
+ a=ccc
+ b=def
+ '[' ccc == def ']'
+ '[' ccc == ccc ']'
+ echo ccc
ccc
9.循环 for while
[root@hadoop000 shell]# vi forwhile.sh
#!/bin/bash
for x in 1 2 3 4 5
do
echo $x
done
echo " "
for ((i=1;i<10;i++))
do
echo $i
done
echo " "
j=1
while(($j<10))
do
echo $j
let "j++"
done
10.分割语法
[root@hadoop000 shell]# vi spilt.sh
#!/bin/bash
s="a,b,c,d,e,f"
OLD_IFS="$IFS"
IFS=","
arr=($s)
IFS="$OLD_IFS"
for x in ${arr[*]}
do
echo $x
done
echo "-----------------------"
arr2=(${s//,/ })
for x in ${arr2[*]}
do
echo $x
done
注:arr2里面最后一个斜杠后面有一个空格。
11.函数
规则:
函数定义在前,调用在后面,从上往下;
只需要使用函数名,即可调用某个函数:
$ fname #执行函数
可以传递参数给函数,并由脚本进行访问:
fname arg1 arg2 # 传递参数
#/bin/bash
#Usage:
# ./function.sh dbname user passwd
#------------------------------------------------------
#Filename: standard.sh
#Revision: 1.0
#Date: xxxx/xx/xx
#Author: xxxxxxx
#Description: The Example of a shell script
#Notes: xxxxxxx
#------------------------------------------------------
function helloworld()
{
echo "hello,world."
}
function sum(){
echo "${1}, ${2}"
SUM=$(( $1 + $2 ))
return $SUM
}
function sum_echo(){
echo "${1}, ${2}"
SUM=$(( $1 + $2 ))
echo $SUM > /root/shell/log/sum.log
}
---------------------------------------------------------
#call function
helloworld
#use $? as return value with range 0~255
sum 1222 33332
echo $?
#use echo as return value
rz=$(helloworld)
echo $rz
sum_echo 123 108
s=`cat /root/shell/log/sum.log`
echo $s
1.helloworld()这里不定义参数。需要参数使用$1 $2来获取,return不写默认输出最后一行
2.结果可以写到临时log,然后再获取赋值给一个变量
3.函数定义在前面 调用在后面
补
$? 上一个命令的执行结果
if条件里的“-a”是and , “-ne”是不等于
ping与ssh的区别,有时候ping通了,但是ssh连不上,(说明网络是通的)
ssh成功才说明能连上。
shell里面的换行
sed "/^$/d"
删除空行
sed "/^#/d"
删除 开头第一个字符是 # 的行 (在很多程序,尤其是shell脚本里,以#开头的行表示注释)
&>/dev/null 一般情况下等价于 >/dev/null 2>&1
生产上不要在shell中直接使用rm-rf,要使用mv移走
补
[ -a FILE ] 如果 FILE 存在则为真。
[ -b FILE ] 如果 FILE 存在且是一个块特殊文件则为真。
[ -c FILE ] 如果 FILE 存在且是一个字特殊文件则为真。
[ -d FILE ] 如果 FILE 存在且是一个目录则为真。
[ -e FILE ] 如果 FILE 存在则为真。
[ -f FILE ] 如果 FILE 存在且是一个普通文件则为真。
[ -g FILE ] 如果 FILE 存在且已经设置了SGID则为真。 [ -h FILE ] 如果 FILE 存在且是一个符号连接则为真。
[ -k FILE ] 如果 FILE 存在且已经设置了粘制位则为真。
[ -p FILE ] 如果 FILE 存在且是一个名字管道(F如果O)则为真。
[ -r FILE ] 如果 FILE 存在且是可读的则为真。
[ -s FILE ] 如果 FILE 存在且大小不为0则为真。
[ -t FD ] 如果文件描述符 FD 打开且指向一个终端则为真。
[ -u FILE ] 如果 FILE 存在且设置了SUID (set user ID)则为真。
[ -w FILE ] 如果 FILE 如果 FILE 存在且是可写的则为真。
[ -x FILE ] 如果 FILE 存在且是可执行的则为真。
[ -O FILE ] 如果 FILE 存在且属有效用户ID则为真。
[ -G FILE ] 如果 FILE 存在且属有效用户组则为真。
[ -L FILE ] 如果 FILE 存在且是一个符号连接则为真。
[ -N FILE ] 如果 FILE 存在 and has been mod如果ied since it was last read则为真。
[ -S FILE ] 如果 FILE 存在且是一个套接字则为真。
[ FILE1 -nt FILE2 ] 如果 FILE1 has been changed more recently than FILE2, or 如果 FILE1 exists and FILE2 does not则为真。
[ FILE1 -ot FILE2 ] 如果 FILE1 比 FILE2 要老, 或者 FILE2 存在且 FILE1 不存在则为真。
[ FILE1 -ef FILE2 ] 如果 FILE1 和 FILE2 指向相同的设备和节点号则为真。
[ -o OPTIONNAME ] 如果 shell选项 “OPTIONNAME” 开启则为真。
[ -z STRING ] “STRING” 的长度为零则为真。
[ -n STRING ] or [ STRING ] “STRING” 的长度为非零 non-zero则为真。
[ STRING1 == STRING2 ] 如果2个字符串相同。 “=” may be used instead of “==” for strict POSIX compliance则为真。
[ STRING1 != STRING2 ] 如果字符串不相等则为真。
[ STRING1 < STRING2 ] 如果 “STRING1” sorts before “STRING2” lexicographically in the current locale则为真。
[ STRING1 > STRING2 ] 如果 “STRING1” sorts after “STRING2” lexicographically in the current locale则为真。
[ ARG1 OP ARG2 ] “OP” is one of -eq, -ne, -lt, -le, -gt or -ge. These arithmetic binary operators return true if “ARG1” is equal to, not equal to, less than, less than or equal to, greater than, or greater than or equal to “ARG2”, respectively. “ARG1” and “ARG2” are integers.
基本上和其他脚本语言一样。没有太大区别。不过值得注意的是。[]里面的条件判断。
字符串判断
str1 = str2 当两个串有相同内容、长度时为真
str1 != str2 当串str1和str2不等时为真
-n str1 当串的长度大于0时为真(串非空)
-z str1 当串的长度为0时为真(空串)
str1 当串str1为非空时为真
数字的判断
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为真
文件的判断
-r file 用户可读为真
-w file 用户可写为真
-x file 用户可执行为真
-f file 文件为正规文件为真
-d file 文件为目录为真
-c file 文件为字符特殊文件为真
-b file 文件为块特殊文件为真
-s file 文件大小非0时为真
-t file 当文件描述符(默认为1)指定的设备为终端时为真
复杂逻辑判断
-a 与
-o 或
! 非