shell脚本27问

【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.

顺序 选择 循环 总结

相关文章
相关标签/搜索