【1】交互方式、非交互方式、Shell脚本是什么?linux
常常与linux打交道,确定对shell这个词不陌生。不明白shell意思的,能够自行翻译:外壳、去壳。shell
这个翻译结果怎么能够与计算机系统联系起来呢?看不懂?小程序
为了帮助理解shell这个词,请看下图:vim
计算机系统,最内层(本质)的是硬件,而后硬件会被系统核心层包住,而在系统核心外层的就是所谓的shell,再而后shell外层的就是咱们接触最多且最容易理解的应用程序。windows
shell实际上是一个命令解释器,做用是解释用户输入的命令和程序,命令和程序能够理解成上图中的应用程序。安全
linux系统中的那些命令其实也都是一个个的小程序,只不过执行的是系统的应用功能。bash
当咱们在系统的终端中输入一条命令,能够立马看到一条或者几条系统回复咱们的信息,其实就是shell在帮咱们回复,因此shell能够称之为命令解释器。服务器
而这种从键盘一输入命令,就立马获得相应的回复信息,叫做交互的方式。函数
了解了shell以后,再来了解下shell脚本。若是咱们的命令或应用程序不在命令行直接执行,而想经过一个程序文件来执行时,这个程序文件就被称之为shell脚本。oop
shell脚本里面一般内置了多条命令,有的还包含控制语句,好比if和else的条件控制语句,for的循环控制语句等。
这些内置在一个shell脚本中的命令一般是一次性执行完成,不会不停的返回信息给用户,这种经过文件执行脚本的方式称之为非交互方式。
shell脚本相似于windows下的批处理,但它比批处理要强大一些,如今windows下有一个叫作power shell的功能其实和linux下的shell功能媲美。
在文本中输入一系列的命令、控制语句和变量,这一切有机的结合起来就造成了功能强大的shell脚本。
平常工做中,常常须要使用多个命令来完成一项任务,能够添加这些全部命令在一个文本文件(Shell脚本)来统一完成这些平常工做任务。
【2】什么是默认登陆shell,如何改变指定用户的登陆shell?
登陆shell是能够用户登陆使用的,好比/bin/bash, /bin/sh, /bin/csh......
通常Linux默认的用户shell都是bash,也就是你能够登陆进去写命令。
非登陆shell:经典的/bin/nologin就是一个非登陆shell,也就是说若是一个用户默认的是它,这个用户即便登陆进linux也没法使用linux。
shell是用户和计算机交流的媒介,登陆shell保证用户和计算机交流,非登陆shell没法让计算机和用户交流。
关于用户的默认登陆shell是在/etc/passwd文件中记录的。本地系统示例以下:
非登陆shell有其特定的用途:好比一个用linux搭建的ftp服务器,建立了多个用户,能够将这些用户默认shell改为nologin。
这样一来,这些用户虽然是linux上的用户却没法登陆进linux主机,只能进入ftp服务器,这样也保证了安全!
在Linux操做系统,“/bin/bash”是默认登陆shell,是在建立用户时分配的。
使用chsh命令能够改变默认的shell。示例以下所示:
# chsh <用户名> -s <新shell>
# chsh zhangsan -s /bin/sh
固然,也能够直接经过修改/etc/passwd文件中对应用户的默认shell。
查看系统中有哪些shell,利用命令:cat /etc/shells
示例以下(本地系统中有六种shell):
【3】能够在shell脚本中使用哪些类型的变量?
在shell脚本,咱们可使用两种类型的变量:
(1)系统定义变量
(2)用户定义变量
系统变量是由系统系统本身建立的。这些变量一般由大写字母组成,能够经过“set”命令查看。
用户变量由系统用户来生成和定义,变量的值能够经过命令“echo $<变量名>”查看。
shell变量的做用域能够分为三种:
(1)有的变量只能在函数内部使用,叫作局部变量(local variable)
(2)有的变量能够在当前shell进程中使用,叫作全局变量(global variable)
(3)有的变量还能够在子进程中使用,叫作环境变量(environment variable)
【4】如何将标准输出和错误输出同时重定向到同一位置?
这里有两个方法来实现:
(1)方法一:2>&1
示例:# ls /usr/share/doc > log.txt 2>&1
前半部分 ls /usr/share/doc > log.txt 很容易理解,那么后面的 2>&1 是怎么回事呢?
要解释这个问题,还得提到文件重定向。假定已经知道 > 和 < 是文件重定向符。那么1和2是什么?
在shell中,每一个进程都和三个系统文件相关联:
(0)标准输入stdin
(1)标准输出stdout
(2)标准错误stderr
三个系统文件的文件描述符分别为0、一、2。因此,这里 2>&1 的意思就是将标准错误也输出到标准输出当中。
& 表示“等同于”的意思,2>&1,表示2的输出重定向等同于1。
实际上,> 就至关于 1> 也就是重定向标准输出,不包括标准错误。
而经过 2>&1 就将标准错误重定向到标准输出了(stderr已做为stdout的副本),那么再使用>重定向就会将标准输出和标准错误信息一同重定向了。
若是只想重定向标准错误到文件中,则可使用 2> file。
(2)方法二:&>
示例:# ls /usr/share/doc &> log.txt
& 是一个描述符,若是1或2前不加&,会被当成一个普通文件。
1>&2 把标准输出重定向到标准错误。
2>&1 把标准错误输出重定向到标准输出。
&> filename 把标准输出和标准错误输出都重定向到文件filename中
摘录同问:Linux重定向中 >&2 怎么理解?
问题补充:echo "abdefghijklmn" >&2 怎么理解?
问题解答:>&2 即 1>&2 也就是把结果输出到和标准错误同样;以前若是有定义标准错误重定向到某log文件,那么标准输出也重定向到这个log文件。
如:ls 2>a1 >&2 (等同 ls >a1 2>&1)
把标准输出和标准错误都重定向到a1,终端上看不到任何输出信息。
【5】shell脚本中“if”语法如何嵌套?
基础语法以下:
if [ 条件 ]
then
命令1
命令2
…
else
if [ 条件 ]
then
命令1
命令2
…
else
命令1
命令2
…
fi
fi
if语法示例以下:
#!/bin/bash a=100 b=200 echo "a : "$a echo "b : "$b if [ $a == $b ] then echo "a 等于 b" elif [ $a -gt $b ] then echo "a 大于 b" elif [ $a -lt $b ] then echo "a 小于 b" else echo "没有符合的条件" fi
if语法输出结果:
a : 100
b : 200
a 小于 b
if嵌套语法示例以下:
#!/bin/bash a=100 b=200 echo "a : "$a echo "b : "$b if [ $a == $b ] then echo "a 等于 b" else if [ $a -gt $b ] then echo "a 大于 b" else if [ $a -lt $b ] then echo "a 小于 b" else echo "没有符合的条件" fi fi fi
if嵌套语法输出结果:
a : 100
b : 200
a 小于 b
【6】shell脚本中“$?”标记的用途是什么?
在写一个shell脚本时,若想要检查前一命令是否执行成功,在if条件中使用“$?”能够来检查前一命令的结束状态。
简单的例子以下:
若是结束状态是0,说明前一个命令执行成功。
若是结束状态不是0,说明命令执行失败。
【7】在shell脚本中如何比较两个数字?
在if-then中使用测试命令(-gt等)来比较两个数字。
-gt示例以下:
#!/bin/bash x=10 y=20 if [ $x -gt $y ] then echo "x is greater than y" else echo "y is greater than x" fi # 输出 # y is greater than x
test示例以下:
#!/bin/bash num1=$[2*3] num2=$[1+5] if test $[num1] -eq $[num2] then echo '两个数字相等!' else echo '两个数字不相等!' fi # 输出 # 两个数字相等!
【8】shell脚本中break命令的做用?
break命令一个简单的用途是退出执行中的循环。
能够在while和until循环中使用break命令跳出循环。
从while循环中跳出,示例以下:
#!/bin/bash a=0 while [ $a -lt 10 ] do echo $a a=`expr $a + 1` if [ $a -gt 8 ] then echo "break" break fi done # 输出 0 1 2 3 4 5 6 7 8 break
从until循环中跳出,示例以下:
#!/bin/bash a=0 until [ ! $a -lt 10 ] do echo $a a=`expr $a + 1` if [ $a -gt 8 ] then break fi done # 输出 0 1 2 3 4 5 6 7 8
从 for 循环中跳出,示例以下:
#!/bin/bash for loop in 1 2 3 4 5 do echo "The value is: $loop" if [ $loop == 4 ] then echo "break" break fi done # 输出 The value is: 1 The value is: 2 The value is: 3 The value is: 4 break
如上三种跳出方式。
【9】shell脚本中continue命令的做用?
continue命令不一样于break命令,它只跳出当前循环的迭代,而不是整个循环。
continue命令不少时候是颇有用的,例如错误发生,但咱们依然但愿继续执行大循环的时候。
示例以下:
#!/bin/bash for i in `seq 1 5` do echo $i if [ $i == 3 ] then continue fi echo $i done echo $i # 输出 1 1 2 2 3 4 4 5 5 5
如上示例。
【10】shell脚本中case语句的语法?
基础语法以下:
case 值 in
模式1)
command1
command2
...
commandN
;;
模式2)
command1
command2
...
commandN
;;
esac
case语法示例以下(用vim 新建文件cash.sh,输入内容):
#!/bin/bash echo '输入 1 到 4 之间的数字:' echo '你输入的数字为:' read aNum case $aNum in 1) echo '你选择了 1' ;; 2) echo '你选择了 2' ;; 3) echo '你选择了 3' ;; 4) echo '你选择了 4' ;; *) echo '你没有输入 1 到 4 之间的数字' ;; esac
如上脚本,执行./case.sh 或 sh case.sh
【11】shell脚本中while循环语法?
如同for循环,while循环只要条件成立就重复它的命令块。
不一样于for循环,while循环会不断迭代,直到它的条件不为真。
基础语法:
while [ 条件 ]
do
命令…
done
【12】如何使脚本可执行?
使用chmod命令来使脚本可执行。示例以下:
# chmod a+x myshell.sh
【13】“#!/bin/bash”的做用?
#!/bin/bash是shell脚本的第一行,称为释伴(shebang)行。
这里#符号叫作hash,而!叫作bang。它的意思是命令经过 /bin/bash 来执行。
【14】shell脚本中for循环语法?
for循环的基础语法:
for 变量 in 循环列表
do
命令1
命令2
…
最后命令
done
【15】如何调试shell脚本?
使用'-x'参数(sh -x myshell.sh)能够调试shell脚本。
如上面例子中的case.sh脚本,调试结果以下:
如上。
【16】shell脚本如何比较字符串?
test命令能够用来比较字符串。测试命令会经过比较字符串中的每个字符来比较。
参数 说明
= 等于则为真
!= 不相等则为真
-z 字符串 字符串的长度为零则为真
-n 字符串 字符串的长度不为零则为真
示例以下(用vim新建test.sh文件,输入以下内容):
#!/bin/bash num1="abcdef" num2="abcdefg" if test $num1 = $num2 then echo '两个字符串相等!' else echo '两个字符串不相等!' fi if test $num1 != $num2 then echo '两个字符串不相等!' else echo '两个字符串相等!' fi if test -z "$num1" then echo 'num1字符串长度为0' else echo 'num1字符串长度不为0' fi num2= if test -n "$num2" then echo 'num2字符串长度不为0' else echo 'num2字符串长度为0' fi # 输出 # 两个字符串不相等! # 两个字符串不相等! # num1字符串长度不为0 # num2字符串长度为0
如上内容。
【17】Bourne shell(bash) 中有哪些特殊的变量?
下面的表列出了Bourne shell为命令行设置的特殊变量。
内建变量 解释
$0 当前脚本的文件名
$n 传递给脚本或函数的参数。n是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2。
$# 传递给脚本或函数的参数个数。
$* 传递给脚本或函数的全部参数。
$@ 传递给脚本或函数的全部参数。被双引号(" ")包含时,与 $* 稍有不一样。可参见下文第【26】问。
$$ 当前shell进程ID。对于shell脚本,就是这些脚本所在的进程ID。
示例以下:
#!/bin/bash echo "0:$0" echo "1:$1" echo "2:$2" echo "3:$3" echo "4:$4" echo "5:$5" echo "6:$6" echo "7:$7" echo "8:$8" echo "9:$9" echo "#:$#" echo "*:$*" echo "@:$@" echo "$:$$"
输出结果:
如上过程。
【18】在shell脚本中,如何测试文件?
test命令能够用来测试文件。
test命令基础用法以下表格:
test 用法
-d 文件名 若是文件存在而且是目录,返回true
-e 文件名 若是文件存在,返回true
-f 文件名 若是文件存在而且是普通文件,返回true
-r 文件名 若是文件存在并可读,返回true
-s 文件名 若是文件存在而且不为空,返回true
-w 文件名 若是文件存在并可写,返回true
-x 文件名 若是文件存在并可执行,返回true
示例以下:
#!/bin/bash if test -e ./shellarg.sh then echo '文件已存在!' else echo '文件不存在!' fi
输出结果:
如上。
【19】在shell脚本中,如何写入注释?
注释能够用来描述一个脚本能够作什么和它是如何工做的。每一行注释以#开头。
示例以下:
#!/bin/bash
# This is a command
【20】如何让shell脚本获得来自终端的输入?
read命令能够读取来自终端(使用键盘)的数据。read命令获得用户的输入并置于你给出的变量中。
示例以下:
#!/bin/bash echo ‘please enter your name’ read name echo “my Name is $name”
输出结果:
如上。
【21】如何取消变量或取消变量赋值?
“unset”命令用于取消变量或取消变量赋值。
语法以下所示:
unset [-fv] [变量或函数名称]
-f:仅删除函数
-v:仅删除变量
应用示例以下:
#!/bin/bash export JAVA_HOME=/usr/local/jdk echo $JAVA_HOME unset JAVA_HOME echo $JAVA_HOME a=100 readonly PI=3.141592653 function func() { echo 'call fun()' } echo 'unset a' unset a func echo 'unset func' unset func echo 'unset PI' unset PI
输出结果:
注意:unset 删除不了只读变量
如上
【22】如何执行算术运算?
有两种方法来执行算术运算:
1.使用expr命令
# expr 5 + 2
2.用一个美圆符号和方括号($[ 表达式 ])
例如:
test=$[16 + 4]
示例以下:
#!/bin/bash a=2 b=3 result1=$[a + b] result2=`expr $a + $b` echo "result1:$result1" echo "result2:$result2"
输出结果:
如上。
【23】在shell脚本如何定义函数呢?
函数是拥有名字的代码块。
当咱们定义代码块,咱们就能够在咱们的脚本调用函数名字,该块就会被执行。示例以下所示:
$ diskusage () { df -h ; }
译注:下面是我给的shell函数语法,原文没有
[ function ] 函数名 [()]
{
命令;
[return int;]
}
示例以下:
#!/bin/bash function demoFunc() { echo "这是个人第一个shell函数!" } echo "-----函数开始执行-----" demoFunc echo "-----函数执行完毕-----"
输出结果:
如上。
【24】shell脚本中如何退出?
利用exit退出整个脚本。
示例以下:
#!/bin/bash for i in `seq 1 5` do echo $i if [ $i == 3 ] then echo "exit" exit fi echo $i done echo "end" # 输出 1 1 2 2 3 exit
如上示例。
【25】shell中如何判断字符串为空?
利用test命令,上面有讲过。
也能够以下示例:
#!/bin/bash string= if [ -z "$string" ]; then echo "string is empty" fi if [ -n "$string" ]; then echo "string is not empty" fi
输出结果:
如上
【26】Shell脚本“$*”和“$@”的联系是什么?
(1)相同点:都是引用全部参数。
(2)不一样点:只有在双引号中体现出来。
假设在脚本运行时写了三个参数 一、二、3,则 " * " 等价于 "1 2 3"(传递了一个参数),而 "@" 等价于 "1" "2" "3"(传递了三个参数)。
(3)示例
3.1 示例以下(利用vim新建脚本文件difference.sh,输出以下内容):
#!/bin/bash echo "-- \$* 演示 ---" for value in "$*"; do echo $value done echo "-- \$@ 演示 ---" for value in "$@"; do echo $value done
3.2 输出结果:
如上
【27】shell 如何实现定时执行任务?
定时器能够直接利用:/bin/sleep 时间(s)
示例以下:
#!/bin/bash echo "timer invite" count=0 while [ true ]; do # 定时器 1s /bin/sleep 1 count=$[count + 1] echo "invite:$count" done
输出结果:
如上。
【28】待续
Good Good Study, Day Day Up.
顺序 选择 循环 总结