Somethign about Shell
[转载自:]http://blog.csdn.net/anders_zhuo/article/details/8644207
#!/bin/bash
echo -n "Enter your name:"
read
echo "read without anyvariables:REPLY=$REPLY"
echo -n "Enter your age:"
read age
echo "read with variable:Age=$age and REPLY=$REPLY"
echo "which one are you skilledin?"
select var in "shell" "java" "c++" "c" "php" "c#"
do
echo "the \$REPLY=$REPLY"
echo "you are skilled in $var"
break
done
count=1
MAX=5
while [ "$SECONDS" -le "$MAX" ]
do
echo "this is the $count time to sleep!"
let count=$count+1
sleep 2
done
echo "this script runs $SECONDS seconds!"
# strlen(str) ${#str} or exptr length $string
# expr index $string $substring
# expr index "Speeding up small jobs in Hadoop" jobs
# 0x13
# get substring
#{string:position:length}
#{...} # 从零开始标记字符串 from left to right
#{string: -position} #冒号和横杆之间有空格 从右边开始取
#{string:(position)}
expr substr $string $position $length #从名称为$string的字符串的第#position位置开始 取长度为$length的子串
delete sunstring
${string#substring} #删除string开头处与substring匹配的最短子串
${string##substring} #删除string子串与substring匹配的最长子串
${string%substring} #删除string结尾处与substring匹配的最短子串
${string%%substring} #删除string结尾处与substring匹配的最长子串
eg
定义一个字符串 20121114ReadingHadoop
ming@ming-F83VF:~/shellpractice/chapter9$anotherstr=20121114ReadingHadoop
ming@ming-F83VF:~/shellpractice/chapter9$echo $anotherstr
20121114ReadingHadoop
删除开头处 以 2开始1结尾的 最短字符串!!
ming@ming-F83VF:~/shellpractice/chapter9$echo ${anotherstr#2*1}
21114ReadingHadoop
删除开头处 以 2开始1结尾的 最长字符串!!
ming@ming-F83VF:~/shellpractice/chapter9$echo ${anotherstr##2*1}
4ReadingHadoop
删除结尾处 以 a开始p结尾的 最短字符串!!
ming@ming-F83VF:~/shellpractice/chapter9$echo ${anotherstr%a*p}
20121114ReadingH
删除结尾处 以 a开始p结尾的 最长字符串!!
ming@ming-F83VF:~/shellpractice/chapter9$echo ${anotherstr%%a*p}
20121114Re
5 替换子串
替换子串命令都是${…}格式,可以在任意处、开头处和结尾处替换满足条件的子串
${string/substring/replacement} #仅替换第一次与substring相匹配的子串
${string//substring/replacement} #替换所有与substring相匹配的子串
${string/#substring/replacement} #替换string开头处与substring相匹配的子串
${string/%substring/replacement} #替换string结尾处与substring相匹配的子串
IO重定向
I/O重定向是一个过程,这个过程捕捉一个文件、或命令、或程序、或脚本、甚至代码块(code block)的输出,然后把捕捉到的输出,作为输入发送给另外一个文件、或命令、或程序、或脚本
文件标识符是从0开始到9结束的整数,指明了与进程相关的特定数据流的源
Linux系统启动一个进程(该进程可能用于执行Shell命令)时,将自动为该进程打开三个文件:标准输入、标准输出和标准错误输出,分别由文件标识符0、1、2标识
Shell命令从标准输入读取输入数据,将输出送到标准输出,如果该命令在执行过程中发生错误,则将错误信息输出到标准错误输出,默认情况下,标准输入与键盘输入相关联,标准输出和标准错误输出与显示器相关联
"" 标准输出: ""
例1
cat和>符号结合成为简易文本编辑器
cat命令后不加任何参数时,cat命令的输入是标准输入,即键盘输入
利用I/O重定向符号“>”将键盘输入写入文件
cat > newfile后,就可输入需要写到newfile的内容,最后按CTRL+D结束对newfile的编辑
例2
>>符号用于在已有文件后追加一些文本
eg
ls >>newfile 只是追加并没有把原来的覆盖掉
ls >newfile 将文件清空,然后将内容写进去
例3
>|符号是强制覆盖文件的符号,它与Shell的noclobber选项有关系,如果noclobber选项开启,表 示不允许覆盖任何文件,而>|符号则可以不管noclobber选项的作用,强制将文件覆盖
eg
ming@ming-F83VF:~/shellpractice/chapter10$set -C noclobber选项开启
ming@ming-F83VF:~/shellpractice/chapter10$date >newfile
bash: newfile: 无法覆盖已存在的文件
ming@ming-F83VF:~/shellpractice/chapter10$date >|newfile
ming@ming-F83VF:~/shellpractice/chapter10$cat newfile
2012年 11月 10日 星期日 09:47:25 CST
标准错误输出:
1
重定向标准错误输出,需要使用文件标识符2
2> newfile
ming@ming-F83VF:~/shellpractice/chapter10$ ls 22*>newfile 此时是将标准输出到 newfile中 但是屏幕中还是会输出,因为他是标准输出
ls: 无法访问22*: 没有那个文件或目录
ming@ming-F83VF:~/shellpractice/chapter10$ls 22* 2>newfile
此时是将标准错误输出到 newfile中所以屏幕中没有任何输出
ming@ming-F83VF:~/shellpractice/chapter10$cat newfile
ls: 无法访问22*: 没有那个文件或目录
2
< 是I/O重定向的输入符号,它可将文件内容写到标准输入之中
ming@ming-F83VF:~/shellpractice/chapter10$ wc -l <newfile
1
这个newfile作为标准输入到wc 所以wc得到的内容只是newfile的内容!!
所以他不会知道这是哪个文件!所以只是打印出了文件行数
ming@ming-F83VF:~/shellpractice/chapter10$wc -l newfile
1 newfile
这个newfile作为wc命令的 操作文件。此时wc知道他要计数的是哪个文件,所以能打印出newfile文件名,因此既打印出了行数也打印出了文件名
<<delimiter 这个比较重要!!!
符号称为此处文档(Here-document),delimiter称为分界符,该符号表明:Shell将分界符delimiter之后直至下一个delimiter之前的所有内容作为输入
ming@ming-F83VF:~/shellpractice/chapter10$cat >newfile <<CLOUD
> hello cloud
> hadoop
> nosql
> CLOUD
(剖析:cat>newfile 是将标准输入到newfile文件中,即键盘输入newfile<<CLOUD是将输入到CLOUD之前的内容作为标准输入在此之前是用ctrl+d 结束标准输入,而使用<< 则是吧CLOUD作为结束标准输入)
ming@ming-F83VF:~/shellpractice/chapter10$cat newfile
hello cloud
hadoop
nosql
父子Shell是相对的,描述了两个Shell进程的fork关系,父Shell指在控制终端或xterm窗口给出提示符的进程,子Shell是由父Shell创建的进程
Shell命令可分为内建命令(built-incommand)和外部命令(external command)内建命令是由Shell本身执行的命令
外部命令由fork出来的子Shell执行
内建命令不创建子Shell,外部命令创建子Shell,因此,内建命令的执行速度要比外部命令快
2) 冒号: 冒号表示永真 相当于 TRUE 关键字
eg
#!/bin/bash
declare -i i=0
while : ;
do
if [ $i -eq 10 ]; then
break
fi
echo $((++i))
done
# 冒号可以被用来清空文件
# :>filename
3) 圆括号可以将其中的命令运行在子shell中
(
command1
command2
...
)
# BASH_SUBSHELL 该变量记录了 shell 的层次·
eg
#!/bin/bash
echo "the level of father shell is $BASH_SUBSHELL"
outvar=outvar
(
echo "the level of sub shell is $BASH_SUBSHELL"
innervar=innervar
echo "outvar=$outvar" #子shell继承了父shell的变量
echo "innervar=$innervar"
)
echo "the level of father shell is $BASH_SUBSHELL"
if [ -z $innervar ]
then
echo "the innervar is $innervar"
else
echo "the outvar is $outvar"
fi
result:
the level of father shell is 0
the level of sub shell is 1
outvar=outvar
innervar=innervar
the level of father shell is 0
the innervar is
由此可见:
子shell继承父shell的变量,而父shell不会得到子shell的变量
另外父shell也不能使用子shell定义的环境变量
4) Shell 的限制模式
以前的Shell模式都是运行在正常模式下的,shell还有一种模式称为限制模式,简称rsh(Restricted Shell),处于限制模式下的shell运行一段代码或者片段,将会禁用一些命令或操作。
shell的限制模式是Linux系统基于安全方面的考虑,目地是为了限制脚本用户的权限,尽可能的减小脚本所带来的危害。
bash Shell的限制模式借鉴了Korn Shell的限制性命令和操作,限制的命令和操作包含如下几方面:
用cd命令更改当前工作目录的命令
更改重要环境变量的值,包括$PATH、$SHELL、$BASH_ENV、$ENV和$SHELLOPTS
输出重定向符号,包括>、>>、>|、>&、<>和&>符号
调用含有一个或多个斜杠(/)的命令名称
使用内建命令exec
使用set +r等命令关闭限制模式
使脚本运行在限制性模式下的两种方式:
第一种:set -r命令开启restricted选项
第二种: #!后的语句改成/bin/bash -r
5) 进程号和作业号
进程号和作业号
Linux系统为每个进程分配一个数字以标识这个进程,这个数字就是进程号
创建该进程的Shell为此进程创建一个数字,也用于标识这个进程,这个数字称为作业号
作业号标识的是在此Shell下运行的所有进程,我们知道,Linux是多用户的系统,多用户可能开启了多个Shell,进程号就标识了整个系统下正在运行的所有进程
举例说明:
[root@jselab shell-book]# grep -r"root" /etc/* | sort > part1 &
[1] 4693
[root@jselab shell-book]# grep -r"root" /usr/local/* | sort > part2 &
[2] 4695
作业有两种运行方式:前台运行和后台运行
前台运行的作业指作业能够控制当前终端或窗口,且能接收用户的输入
后台运行的作业则不在当前激活的终端或窗口中运行,是在用户“看不见”的情况下运行
内建命令fg可将后台运行的作业放到前台,
而&符号使得作业后台运行,
CTRL+Z组合键可以使作业转入阻塞态,
bg命令可使阻塞态作业转入后台运行
fg、bg和jobs命令只能以作业号为参数来指定作业,这三个命令是不能使用进程号的
disown命令用于从Shell的作业表中删除作业,作业表指得就是由jobs命令所列出的作业列表
wait命令用于等待后台作业完成,
6) 信号
信号是Linux进程间通信的一个重要而复杂的概念,信号是在软件层次上对中断机制的一种模拟
信号是异步的,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达
信号来源:硬件来源和软件来源
组合键
信号类型
意义
CTRL+C INT信号,即interrupt信号 停止当前运行的作业
CTRL+Z TSTP信号,即terminal stop信号 使当前运行的作业暂时停止(转入阻塞态)
CTRL+\ QUIT信号 CTRL+C的强化版本,当CTRL+C无法停止作业时,使用此组合键
CTRL+Y TSTP信号,即terminal stop信号 当进程从终端读取输入数据时,暂时停止该进程
对于shell能执行 停止 暂停等功能,是因为向shell发送了了信号。
如表中信号:INT TSTP等
CTRL+C,INT信号,退出作业
CTRL+\, QUIT信号, CTRL+C的强化版本
CTRL+Y组合键实际上与CTRL+Z组合键是类似的,都是向进程发送TSTP信号,表示将进程暂时停止
kill命令可以通过进程号、作业号或进程命令名向任何作业发送信号
kill –l列出kill命令能发出的所有信号
7) trap命令
trap是Linux的内建命令,它用于捕捉信号
指定收到某种信号时所执行的命令
trap command sig1 sig2 …sigN
trap命令表示当收到sig1、sig2、…、sigN中任意一个信号时,执行command命令,command命令完成后脚本继续收到信号前的操作,直到脚本执行结束
eg
[plain] view plaincopy
#!/bin/bash
trap "echo 'execute trap !'" INT #接收 INT信号 即ctrl + c
count=1
while : ;
do
echo "this is $count"
let "count+=1"
sleep 5
done
运行结果:每当 按下ctrl+c的时候都会被trap接收到,然后执行引号中的命令
anders@anders-virtual-machine:~/code/shell/subandthread$./trap1.sh
this is 1
this is 2
^Cexecute trap !
this is 3
^Cexecute trap !
this is 4
^Cexecute trap !
trap命令还可以
忽略某些信号,即进程收到某些信号后不做任何处理,我们只要简单将trap命令的command用空字符串代替即可(""或'')
#!/bin/bash
trap "" TERM SIGKILL INT
while :; do
#let count=count+1
#echo "This is the $count sleep"
sleep 5
done