shell脚本57问
【1】交互方式、非交互方式、Shell脚本是什么?
经常与linux打交道,肯定对shell这个词不陌生。不明白shell意思的,可以自行翻译:外壳、去壳。
这个翻译结果怎么可以与计算机系统联系起来呢?看不懂?
为了帮助理解shell这个词,请看下图:
计算机系统,最内层(本质)的是硬件,然后硬件会被系统核心层包住,而在系统核心外层的就是所谓的shell,再然后shell外层的就是我们接触最多且最容易理解的应用程序。
shell其实是一个命令解释器,作用是解释用户输入的命令和程序,命令和程序可以理解成上图中的应用程序。
linux系统中的那些命令其实也都是一个个的小程序,只不过执行的是系统的应用功能。
当我们在系统的终端中输入一条命令,可以立马看到一条或者几条系统回复我们的信息,其实就是shell在帮我们回复,所以shell可以称之为命令解释器。
而这种从键盘一输入命令,就立马得到相应的回复信息,叫作交互的方式。
了解了shell之后,再来了解下shell脚本。如果我们的命令或应用程序不在命令行直接执行,而想通过一个程序文件来执行时,这个程序文件就被称之为shell脚本。
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、1、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=
b=
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=
b=
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=
y=
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=$[*]
num2=$[+]
if test $[num1] -eq $[num2]
then
echo '两个数字相等!'
else
echo '两个数字不相等!'
fi # 输出
# 两个数字相等!
【8】shell脚本中break命令的作用?
break命令一个简单的用途是退出执行中的循环。
可以在while和until循环中使用break命令跳出循环。
从while循环中跳出,示例如下:
#!/bin/bash a=
while [ $a -lt ]
do
echo $a
a=`expr $a + `
if [ $a -gt ]
then
echo "break"
break
fi
done # 输出 break
从until循环中跳出,示例如下:
#!/bin/bash a=
until [ ! $a -lt ]
do
echo $a
a=`expr $a + `
if [ $a -gt ]
then
break
fi
done # 输出
从 for 循环中跳出,示例如下:
#!/bin/bash for loop in
do
echo "The value is: $loop"
if [ $loop == ]
then
echo "break"
break
fi
done # 输出
The value is:
The value is:
The value is:
The value is:
break
如上三种跳出方式。
【9】shell脚本中continue命令的作用?
continue命令不同于break命令,它只跳出当前循环的迭代,而不是整个循环。
continue命令很多时候是很有用的,例如错误发生,但我们依然希望继续执行大循环的时候。
示例如下:
#!/bin/bash for i in `seq `
do
echo $i
if [ $i == ]
then
continue
fi
echo $i
done
echo $i # 输出
如上示例。
【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
) echo '你选择了 1'
;;
) echo '你选择了 2'
;;
) echo '你选择了 3'
;;
) 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脚本?
两种方式:
(1)使用‘-x’参数(sh -x myshell.sh)可以调试shell脚本。
如上面例子中的case.sh脚本,调试结果如下:
如上。
(2)使用‘-xv’参数,但是,写法与第一种不同,具体如下:
#!/bin/bash -xv
应用示例如下:
#!/bin/bash -xv
echo '输入 1 到 4 之间的数字:'
echo '你输入的数字为:'
read aNum
case $aNum in
) echo '你选择了 1'
;;
) echo '你选择了 2'
;;
) echo '你选择了 3'
;;
) echo '你选择了 4'
;;
*) echo '你没有输入 1 到 4 之间的数字'
;;
esac
输出结果:
如上。
【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=
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=
b=
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 `
do
echo $i
if [ $i == ]
then
echo "exit"
exit
fi
echo $i
done
echo "end" # 输出 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)不同点:只有在双引号中体现出来。
假设在脚本运行时写了三个参数 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=
while [ true ]; do
# 定时器 1s
/bin/sleep
count=$[count + ]
echo "invite:$count"
done
输出结果:
如上。
【28】如何向脚本传递参数?
不懂shell的同事,可能不会修改shell代码(比如测试的妹子)。
那么,为了让脚本更通用,某些变量值需要在执行脚本时传入即可。
因某种需要,想在脚本执行时传入运行过程中的需要的参数。
示例如下(用vim新建文件argument.sh,输入如下内容):
#!/bin/bash echo "第一个参数值:$1"
echo "第二个参数值:$2"
输出结果:
如上
【29】shell脚本如何读取文件?
工作中,最常用的就是利用shell脚本读取文件(比如日志文件log)。
shell脚本读取(read)文件,利用循环逐行进行读取。
示例如下:
#!/bin/bash echo "-------begin read file"
while read -r line
do
echo $line
done < $
echo "-------end read file"
输出结果:
如上。注意:利用上一问的脚本传参方式将文件名作为参数传入。
【30】如何获取一个文件每一行的第三个元素?
使用 awk '{print $3}'
应用示例如下:
#!/bin/bash echo "-------begin read file content"
while read -r line
do
echo $line
done < $
echo "-------end read file content" echo "---------begin read three column"
awk '{print $3}' $
echo "---------end read three column"
输出结果:
如上。
如何获取一个文件每一行的第三个元素 ?
作者:IT程序狮
链接:http://www.imooc.com/article/1131
来源:慕课网
【31】如何获取文件的第一行和最后一行内容?
获取首行:head -1
获取尾行:tail -1
应用示例如下:
#!/bin/bash echo "------begin read file content"
while read -r line
do
echo $line
done < $
echo "------end read file content" echo "------begin read head line"
head - $
echo "------end read head line" echo "------begin read tail line"
tail - $
echo "------end read tail line"
输出结果:
如上。
【32】假如文件中某一行的第三个元素是18,如何获取第四个元素?
使用:awk '{ if ($3 == "18") print $4}'
应用示例如下:
#!/bin/bash echo "-------begin read file content"
while read -r line
do
echo $line
done < $
echo "-------end read file content" echo "------begin four column value"
awk '{ if ($3 == "18") print $4}' $
echo "------end four column value"
输出结果:
如上。
【33】如何连接两个字符串?
应用示例如下:
#!/bin/bash v1="bei"
v2="jing"
echo "------字符串连接前"
echo "v1:$v1"
echo "v2:$v2"
echo "------字符串连接方式一后"
v3=${v1}${v2}
echo "v3:$v3"
echo "------字符串连接方式二后"
echo "$v1$v2"
输出结果:
如上。
【34】shell脚本中如何进行两数相加?
方式共有六种。
应用示例如下:
#!/bin/bash A=
B=
echo "------原数据"
echo "A:$A"
echo "B:$B"
echo "------方式一"
let C=$A+$B
echo $C
echo "------方式二"
echo $(($A+$B))
echo "------方式三"
echo $[$A+$B]
echo "------方式四"
expr $A + $B
echo "------方式五"
echo $A+$B | bc
echo "------方式六"
awk 'BEGIN{print '"$A"'+'"$B"'}'
输出结果:
如上。
【35】每个脚本开始的 #!/bin/sh 或 #!/bin/bash 表示什么意思?
这一行说明要使用的 shell。#!/bin/bash 表示脚本使用 /bin/bash。对于 python 脚本,就是 #!/usr/bin/python。
【36】如何获取文本文件的第2行?
使用:head -2 file | tail -1
示例应用如下:
#!/bin/bash echo "------begin read file content"
while read -r line
do
echo $line
done < $
echo "------end read file content" echo "------begin read second line"
head - $ | tail -
echo "------end read second line"
输出结果:
如上。
【37】bash脚本文件的第一个符号是什么?
答:#
【38】命令:[ -z "" ] && echo 0 || echo 1 的输出是什么?
关于“-z” 可参考上面第15问理解:字符串长度为零则为真
关于&& 和 ||,即分别为shell脚本的逻辑运算符AND 和 OR
所以,[ -z "" ] 的值为真,那么:[ -z "" ] && echo 0 输出结果即为:0
示例如下:
#!/bin/bash echo " expression result"
[ -z "" ] && echo || echo
echo "end" echo "逻辑运算符演示"
a=
b= if [[ $a -lt && $b -gt ]]
then
echo "返回 true"
else
echo "返回 false"
fi if [[ $a -lt || $b -gt ]]
then
echo "返回 true"
else
echo "返回 false"
fi
输出结果:
如上。
【39】命令 “export” 有什么用?
使父shell定义的变量在子shell进程中可以使用。
用户登录到linux系统后,系统将启动一个用户shell。
在这个shell中,可以使用shell命令或声明变量,也可以创建并运行shell脚本程序。当运行shell脚本程序时,系统将创建一个子shell。
此时,系统中将有两个shell,一个是登录时系统启动的shell,另一个是系统为运行脚本程序创建的shell。
当一个脚本程序运行完毕,脚本shell(即子shell)将终止,返回到执行该脚本之前的shell。
从这种意义上来说,用户可以有许多shell,每个shell都是由某个shell(称为父shell)生的。
在子shell中定义的变量只在该子shell内有效。
即在一个shell脚本程序中定义了一个变量,当该脚本程序运行时,这个定义的变量只是该脚本程序内的一个局部变量,其他的shell不能引用它。
如果要使某个变量的值可以在其他shell中被改变,可以使用export命令对已定义的变量进行输出。
export命令将使系统在创建每一个新的shell时,定义这个变量的一个拷贝。这个过程称之为变量输出。
(1)修改生效范围
脚本A中export的变量在启动其他脚本时会复制一份传入其他脚本。其他脚本中对此变量的修改并不会在离开脚本后生效。
(2)注意
在脚本A中定义了一个变量V赋值为1,export了变量V,在脚本A中启动脚本B,在脚本B中变量V的值就是1,如果在脚本B中修改了V的值为2,那么脚本B结束后,脚本A中的V的值依然是1。
脚本A中export的变量在启动其他脚本的时候会复制一份传入其他脚本,传入的值是调用其他脚本时的值。并不是export时的值。
在脚本A中定义了一个变量V赋值为1,export了变量V,然后修改V为2,在脚本A中启动脚本B,在脚本B中变量V的值就是2。
应用示例如下:
使用vim创建脚本文件export_b.sh,输入如下内容:
#!/bin/bash echo "exec export_b start" A="this is export_b A"
export B="this is export_b B" ./export_a.sh echo "export_b A:$A"
echo "export_b B:$B"
echo "exec export_b over"
使用vim创建脚本文件export_a.sh,输入如下内容:
#!/bin/bash echo "exec export_a start" echo "this is export_a, A=\"$A\""
echo "this is export_a, B=\"$B\"" A="this is export_a A"
B="this is export_b B" echo "exec export_a over" exit
输出结果:
如上。
【40】如何在后台运行脚本?
主要分为以下三种需求场景:
(1)前台转后台运行脚本
[1] 执行脚本backrun.sh:./backrun.sh
[2] 中断脚本backrun.sh:ctrl+c
[3] 在[1]的基础上将运行中的backrun.sh,切换到后台并暂停:ctrl + z
[4] 执行ctrl + z 后,backrun.sh在后台是暂停状态(stopped)。
使用命令:bg number让其在后台开始运行(“number”是使用jobs命令查到的[ ]中的数字,不是pid)
(2)后台转前台运行脚本
[1] 直接在后台运行脚本backrun.sh:./backrun.sh &
[2] 查看当前shell环境中已启动的任务情况:jobs
[3] 将backrun.sh切换到前台运行:fg %number(”number”为使用jobs命令查看到的[ ]中的数字,不是pid)
[4] 中断后台运行的backrun.sh脚本:先fg %number切换到前台,再ctrl+c;或直接kill %number
尤其注意:以上两种在后台运行backrun.sh的方法,当遇到退出当前shell终端时,后台运行的backrun.sh也就结束了。为什么呢?
因为以上两种方法之所以使得backrun.sh在后台运行,运行backrun.sh进程的父进程是当前shell终端进程,关闭当前shell终端时,父进程退出,会发送hangup信号给所有子进程,子进程收到hangup以后也会退出。
所以要想退出当前shell终端时backrun.sh继续运行,则有两种方式:
方式一:使用nohup忽略hangup信号
[1] 不中断的在后台运行backrun.sh:nohup ./backrun.sh &(backrun.sh的打印信息会输出到当前目录下的nohup.out中)
[2] 使用jobs可看到backrun.sh处于running状态
[3] 使用ps -ef | grep backrun.sh可查看到正在运行的backrun.sh脚本进程
[4] 退出当前shell终端,再重新打开,使用jobs看不到正在运行的backrun.sh,但使用ps -ef可以看到
方式二:使用setsid将其父进程改为init进程(进程号为1)
[1] 不中断的在后台运行backrun.sh另一个命令:setsid ./backrun.sh &
[2] 使用ps -ef | grep backrun.sh可看到backrun.sh进程的父进程id为1
示例脚本程序如下:
#!/bin/bash count=
while (( $count <= ))
do
echo $count
let "count++"
sleep
done
自己运行体会。
【41】"chmod 500 myscript.sh" 做什么?
使脚本所有者拥有可执行权限。
对于Linux系统中的文件来说,有三种身份和四种权限,三种身份是:
u:文件的拥有者
g:文件所属的群组
o:其他用户
对于每个身份,又有四种权限,分别为:
r:读取文件的权限(read)
w:写入文件的权限(write)
x:执行的权限(execute)
s:特殊权限
说这么多,那500又是怎么回事呢?这其实也是Linux系统下一种表示文件权限的方式:
在Linux系统中,对于文件的权限有读取、写入、执行三种,分别用rwx表示,另一种表示权限的方式就是使用数字,读取、写入和执行权限分别由数字4、2和1表示:
读取权限:r 或者4
写入权限:w 或者2
执行权限:x 或者1
如下图:
那么,对于此例中的文件,用数字形式表示其权限的话,则为500,如下所示:
如上。
【42】">" 和 ">>" 做什么?
重定向输出流到文件或另一个流。
两者的区别:
(1)> :如果文件不存在,会创建文件。如果文件存在,就将其清空。即会重写文件,如果文件里面有内容会覆盖。
(2)>> :如果文件不存在,会创建文件。如果文件存在,将输出内容追加到目标文件中。
示例如下(为了便于演示,只演示>>的场景。利用上问的脚本):
#!/bin/bash count=
while (( $count <= ))
do
echo $count >> backrun.log
let "count++"
sleep
done
输出结果:
注意:
因为输出重定向到日志文件backrun.log文件中,所以启动脚本后,shell端看不到输入内容。
只能通过浏览backrun.log文件查看执行结果。
如上。
【43】“&”、“&&”和“;”有什么区别?
& :希望脚本在后台运行的时候使用它
&& :当前面的脚本执行成功后,才执行后面的脚本或命令
;:不管前面的脚本命令执行成功与否,后面的脚本或命令继续执行
如下三种形式:
1.command1 & command2 & command3
表示:三个命令同时执行
2.command1; command2; command3
表示:不管前面命令执行成功没有,后面的命令继续执行
3.command1 && command2
表示:只有前面命令执行成功,后面命令才继续执行
利用上问的脚本command1.sh,改造如下(从1开始计数):
#!/bin/bash count=
while (( $count <= ))
do
echo $count
let "count++"
sleep
done
command2.sh,改造如下(从100开始计数):
#!/bin/bash count=
while (( $count <= ))
do
echo $count
let "count++"
sleep
done
command3.sh,改造如下(从1000开始计数):
#!/bin/bash count=
while (( $count <= ))
do
echo $count
let "count++"
sleep
done
执行命令command4.sh,内容如下(可尝试修改三种方式运行观察):
#!/bin/bash ./command1.sh & ./command2.sh & ./command3.sh
自己摸索体会其差异点。
【44】 ' 和 " 引号有什么区别?
' - 当我们不希望把变量转换为值的时候使用它。
” - 会计算所有变量的值并用值代替。
应用示例如下:
#!/bin/bash name=John && echo "My name is $name"
age= && echo 'My age is $age'
输出结果:
如上。
【45】如何只用echo命令获取字符串变量的一部分?
应用示例如下:
#!/bin/bash echo "----按索引截取"
variable="My name is wangjun, and I am developer"
echo ${variable::} localpath="User:192.168.1.15:/home/wangjun"
echo "----截取尾部方式一:"
echo ${localpath#*:*.*.*.*:}
echo "----截取尾部方式二:"
echo ${localpath##*:} echo "----截取头部方式一:"
echo ${localpath%:*.*.*.*}
echo "----截取头部方式二:"
echo ${localpath%%:*} echo "----截取中间字符串"
data=`echo ${localpath#*User:}`
ip=`echo ${data%:/home*}`
echo "${ip}"
输出结果:
如上。
【46】如何获取变量长度且获取变量最后10个字符?
应用示例如下:
#!/bin/bash value="abcdefghijklmnopqrstuvwxyz"
echo "value length:${#value}"
if [ ${#value} -gt ]
then
echo "print tail 10:"
echo ${value: -}
fi
输出结果:
如上。
【47】${variable:-10} 和 ${variable: -10} 有什么区别?
应用示例如下:
#!/bin/bash variable=
echo ${variable:-}
echo ${variable: -} variable="abcdefghijklmn"
echo ${variable:-}
echo ${variable: -}
输出结果:
总结:
${variable:-10} :如果之前没有给 variable 赋值则输出10;如果有赋值则输出该变量。
${variable: -10}:输出variable的最后10个字符。
如上。
【48】如何只用echo命令替换字符串的一部分?
示例如下:
#!/bin/bash variable="abcdefghijklmn"
echo "方式一:${variable//def/wangqi}"
echo 方式二:${variable//def/wangqi}
输出结果:
如上。利用echo ${variable//pattern/replacement}进行替换操作。
【49】如何将文本文件中的小写字符转换为大写?
tr [:lower:] [:upper:]
应用示例如下:
#!/bin/bash cat $ | tr [:lower:] [:upper:]
输出结果:
如上。
【50】如何列出第二个字母是a 或 b的文件?
ls -d ?[ab]*
应用示例,输出结果:
如上。
【51】如何去除字符串中的所有空格?
echo $string | tr -d " "
应用示例如下:
#!/bin/bash var="I am wang qi and my age is 18."
echo "var:$var"
echo $var | tr -d " "
输出结果:
如上。
【52】重写这个命令,将输出变量转换为复数: item="car"; echo "I like $item" ?
重写脚本如下:
#!/bin/bash item="car"
echo "I like ${item}s"
输出结果:
如上。
【53】写出输出数字 0 到 20 中 3 的倍数(0 3 6 9 …)的命令?
脚本如下:
#!/bin/bash echo "方式一:"
for i in {....}; do
echo $i
done echo "方式二:"
for (( i=; i<; i=i+)); do
echo "Welcome $i times"
done
输出结果:
如上。
【54】[ $a == $b ] 和 [ $a -eq $b ] 有什么区别?
[ $a == $b ] - 用于字符串比较
[ $a -eq $b ] - 用于数字比较
【55】[[ $string == abc* ]] 和 [[ $string == "abc" ]] 有什么区别?
[[ $string == abc* ]] - 检查字符串是否以字母 abc 开头
[[ $string == "abc" ]] - 检查字符串是否完全等于 abc
应用示例如下:
#!/bin/bash string="abcdefhigk"
if [[ $string == abc* ]] ;
then
echo "string is start with abc"
else
echo "string is not start with abc"
fi if [[ $string == "abc" ]] ;
then
echo "string is abc"
else
echo "string is not abc"
fi
输出结果:
如上。
【56】如何打印数组中的所有元素?
应用示例如下:
#!/bin/bash array=("Hi" "my" "name" "is") echo "打印数组第一个元素"
echo ${array[]} echo "打印数组的所有元素"
echo ${array[@]} echo "输出所有数组索引"
echo ${!array[@]} echo "移除数组中索引为2的元素"
unset array[]
echo ${array[@]} echo "在数组中添加id为110的元素"
array[]="new_element_110" echo ${array[@]}
输出结果:
如上。
【57】不用 wc 命令如何计算字符串中的单词数目?
应用示例如下:
#!/bin/bash string="my name is wang qi and my age is 18" echo $string
set ${string}
echo count:$#
输出结果:
如上。
【58】shell脚本如何进行数据库操作?
以mysql数据库为例。不用在mysql的提示符下运行mysql,在shell脚本中操作mysql的方法:
mysql -hhostname -Pport -uusername -ppassword -e 执行的sql语句
应用示例如下:
#!/bin/bash HOSTNAME="119.254.95.194"
PORT=""
USERNAME="root"
PASSWORD="" use_sql="use billing;"
mysql -h${HOSTNAME} -P${PORT} -u${USERNAME} -p${PASSWORD} -e "${use_sql}" select_sql="use billing; select * from cfg_dict into outfile '/var/lib/mysql/cfg_dict.csv' fields terminated by ',';"
mysql -h${HOSTNAME} -P${PORT} -u${USERNAME} -p${PASSWORD} -e "${select_sql}"
如上。
【59】待续....
Good Good Study, Day Day Up.
顺序 选择 循环 总结
shell脚本57问的更多相关文章
- 面试linux运维一定会问到Shell脚本这24个问题
面试linux运维一定会问到Shell脚本这24个问题 虽然现在Python在运维工作中已经使用很普遍,但是很多企业在找Linux云计算工程师的时候还是会问到 shell 脚本的问题,它有助于你在工作 ...
- Linux Shell脚本面试25问
Q:1 Shell脚本是什么.它是必需的吗? 答:一个Shell脚本是一个文本文件,包含一个或多个命令.作为系统管理员,我们经常需要使用多个命令来完成一项任务,我们可以添加这些所有命令在一个文本文件( ...
- 【转】Linux Shell脚本面试25问
Q:1 Shell脚本是什么.它是必需的吗? 答:一个Shell脚本是一个文本文件,包含一个或多个命令.作为系统管理员,我们经常需要使用多个命令来完成一项任务,我们可以添加这些所有命令在一个文本文件( ...
- 《Linux命令行与shell脚本编程大全 第3版》Shell脚本编程基础---57
以下为阅读<Linux命令行与shell脚本编程大全 第3版>的读书笔记,为了方便记录,特地与书的内容保持同步,特意做成一节一次随笔,特记录如下:
- 《Linux命令行与shell脚本编程大全 第3版》Linux命令行---57
以下为阅读<Linux命令行与shell脚本编程大全 第3版>的读书笔记,为了方便记录,特地与书的内容保持同步,特意做成一节一次随笔,特记录如下:
- 用 shell 脚本做 restful api 接口监控
问题的提出 基于历史原因,公司有一个"三无"采集服务--无人员.无运维.无监控--有能力做的部门不想接.接了的部门没能力.于是就一直这样裸奔,直到前几天一个依赖于这个采集服务的大数 ...
- 【转】70个经典的 Shell 脚本面试问题
我们为你的面试准备选择了 70 个你可能遇到的 shell 脚面问题及解答.了解脚本或至少知道基础知识对系统管理员来说至关重要,它也有助于你在工作环境中自动完成很多任务.在过去的几年里,我们注意到所有 ...
- linux下shell脚本执行jar文件
最近在搞一个shell脚本启动jar文件个关闭jar文件的东东.搞得我都蛋疼了.今天晚上终于弄好了 话说,小弟的linux只是刚入门,经过各方查资料终于搞定了.话不多说,下面开始上小弟写的shell脚 ...
- 常用的主机监控Shell脚本
最近时不时有朋友问我关于服务器监控方面的问题,问常用的服务器监控除了用开源软件,比如:cacti,nagios监控外是否可以自己写shell脚本呢?根据自己的需求写出的shell脚本更能满足需求,更能 ...
随机推荐
- NHibernate官方文档——第八章 继承映射(Inheritance Mapping)
本文翻译自NHibernate官方文档NHibernate Reference Documentation 4.1. 受限于个人知识水平,有些地方翻译可能不准确,但是我还是希望我的这些微薄的努力能为他 ...
- linux下打包,压缩,解压缩
Linux下最常用的打包程序就是tar了,使用tar程序打出来的包我们常称为tar包,tar包文件的命令通常都是以.tar结尾的.生成tar包后,就可以用其它的程序来进 行压缩了,所以首先就来讲讲ta ...
- 彻底理解Javascript 中的 Promise(-------------------------------***---------------------------------)
ES6原生提供了 Promise 对象. 到底是何方妖怪呢?打出来看看: 所谓 Promise,就是一个对象,用来传递异步操作的消息.它代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个 ...
- JDBCUtils工具类
JdbcUtils.java import java.sql.Connection; import java.sql.SQLException; import javax.sql.DataSource ...
- Asp.net问题集锦
1.在Web应用开发中经常碰到这样的情况,Dropdownlist绑定的数据太多,用户要选择某一项必须从头找到尾,使用起来很不方便.最近我在工作中就碰到这种情况,公司内某个业务系统需要绑定几百条的厂家 ...
- Rails中nil? empty? blank? present?的区别
.nil? Ruby方法 .nil?方法被放置在Object类中,可以被任何对象调用,如果是nil则返回true 在Rails中只有nil对象才会返回true nil.nil? #=> true ...
- 关于web后门权限防删的一个新思路
见土司有一帖子 具体看下面连接 https://www.t00ls.net/thread-26444-1-2.html 这是php的 其实IIS也有类似的 这是MSF生成的一个ASPX执行shellc ...
- Laravel服务/服务提供者/容器/契约和门面
1.服务是什么? 服务是提供了一些功能的类,比如发送邮件,写日志. 2.Laravel服务提供者是什么? 服务提供者中指明了这个提供者可以提供哪些服务(注册服务),以及服务注册后默认调用一些方法(bo ...
- PHP结巴程序实现
<?php $str="我...我要要要...学学学..编编程"; $str=preg_replace('/\./','',$str);//我我要要要学学学编编程 $str= ...
- STL学习笔记(迭代器配接器)
Reverse(逆向)迭代器 Reverse迭代器是一种配接器. 重新定义递增运算和递减运算.使其行为正好倒置. 如果你使用这类迭代器,算法将以逆向次序处理元素.所有标准容器都允许使用Reverse迭 ...