这篇文章给大家分享的是有关shell知识点有哪些的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。
$? 前一命令退出状态,0表示成功
$$ shell进程ID
PPID 父进程ID
LANG 当前Locale的默认名称,其他LC_*变量会覆盖此值
LC_ALL 当前Locale名称,会覆盖LANG和其他LC_*
PS1(prompt sign) 当前提示字符串
exit 终止整个脚本的执行
return 退出当前函数并返回数字 return N或者$?
shift
shift 3表示原来的$4现在变成$1,原来的$5现在变成$2等等,原来的$1、$2、$3丢弃,$0不移动。不带参数的shift命令相当于shift 1
getopts
http://blog.sina.com.cn/s/blog_674b5aae0100o2nz.html
getopts一般格式为:getopts option_string variable
指定变量取值,即在option_string中将一个冒号放在选项后;但当冒号放在第一个选项时,代表其作为一个选项存在;
具体含意为如果某选项设置为取值传递但却未传值时,返回该选项后的信息,若未添加此选项则默认系统也会返回一个错误信息,只是错误信息提示并不明确。
如getopts ahfvc: option表明选项a、h、f、v可以不加实际值进行传递,而选项c必须取值。使用选项取值时,必须使用变量OPTARG保存该值。
在使用getopts命令的时候,shell会自动产生两个变量OPTIND和OPTARG。
OPTIND初始值为1,其含义是下一个待处理的参数的索引。只要存在,getopts命令返回true,所以一般getopts命令使用while循环;
OPTARG是当getopts获取到其期望的参数后存入的位置。
#!/bin/bash
if [ $# -lt 1 ]
then
echo "there is no option";
else
while getopts ":Iti:s:v" opt;
do
case $opt in
I)echo "option is I "
;;
t)echo "option is t "
;;
i)ii=$OPTARG;echo "option is i,the value is $ii";
;;
s)ss=$OPTARG;echo "option is s ,the value is $ss";
;;
v)echo "option is v \n";
;;
:)
echo ">>> Error: '-$OPTARG' requires an argument"
;;
?)paralist=-1;
echo ">>> Error: '-$OPTARG' not supported,please input valid argument [Itisv]"
;;
esac
done
fi
下面给出几个执行的例子:
(1)sh datediff.sh -i 1 -I -v
option is i,the value is 1
option is I
option is v \n
(2)sh datediff.sh -s -i 1
option is s, the value is -i //取s选项后的值
(3)sh datediff.sh -s //选项中有前置冒号
>>> Error: '-s' requires an argument
sh datediff.sh -s //去除选项中的前置冒号后的输出
datediff.sh: option requires an argument -- s
>>> Error: '-' not supported,please input valid argument [Itisv]
subshell和代码块
前者由()包围,后者则是{};
subshell可以在行上任何位置执行,会创建一个新进程,除此之外,调用&提交后台作业/管道,都会创建新进程;
代码块只能位于换行字符、分号或关键字之后,与主脚本共享状态;
http://stackoverflow.com/questions/5547787/running-shell-script-in-parallel
subshell模拟并行运算
#!/bin/bash
for i in $(seq 1 1000)
do
( Generating random numbers here , sorting and outputting to file$i.txt ) &
if (( $i % 10 == 0 )); then wait; fi # Limit to 10 concurrent subshells.
done
wait
tee
http://linux.chinaunix.net/docs/2007-08-07/4538.shtml
tee命令会从标准输入读取数据,将其内容输出到标准输出设备,同时又可将内容保存成文件。例如有如下的脚本片段,其作用是获取本机的ip地址:
ipaddr=`/sbin/ifconfig | grep 'inet addr:' | grep -v '127.0.0.1' | cut -d : -f3 | awk '{print $1}'`
#注意=号后面的整句是用反引号(数字1键的左边那个键)括起来的。
echo $ipaddr
运行这个脚本,实际输出的却不是本机的ip地址,而是广播地址,这时我们可以借助tee命令,输出某些中间结果,将上述脚本片段修改为:
ipaddr=`/sbin/ifconfig | grep 'inet addr:' | grep -v '127.0.0.1' | tee temp.txt | cut -d : -f3 | awk '{print $1}'`
echo $ipaddr
之后,将这段脚本再执行一遍,然后查看temp.txt文件的内容:
$ cat temp.txt
inet addr:192.168.0.1 Bcast:192.168.0.255 Mask:255.255.255.0
我们可以发现中间结果的第二列(列之间以:号分隔)才包含了IP地址,而在上面的脚本中使用cut命令截取了第三列,
故我们只需将脚本中的cut -d : -f3改为cut -d : -f2即可得到正确的结果
trap
http://linux.chinaunix.net/docs/2007-08-07/4538.shtml
trap命令用于捕获指定的信号并执行预定义的命令。
其基本的语法是:
trap 'command' signal
其中signal是要捕获的信号,command是捕获到指定的信号之后,所要执行的命令。
可以用kill –l命令看到系统中全部可用的信号名,捕获信号后所执行的命令可以是任何一条或多条合法的shell语句,也可以是一个函数名。
shell脚本在执行时,会产生三个所谓的“伪信号”,之所以称之为“伪信号”是因为这三个信号是由shell产生的,而其它的信号是由操作系统产生的
表 1. shell伪信号
信号名 何时产生
EXIT 从一个函数中退出或整个脚本执行完毕
ERR 当一条命令返回非零状态时(代表命令执行不成功)
DEBUG 脚本中每一条命令执行之前
通过捕获EXIT信号,我们可以在shell脚本中止执行或从函数中退出时,输出某些想要跟踪的变量的值,并由此来判断脚本的执行状态以及出错原因,其使用方法是:
trap 'command' EXIT 或 trap 'command' 0
通过捕获ERR信号,我们可以方便的追踪执行不成功的命令或函数,并输出相关的调试信息,
以下是一个捕获ERR信号的示例程序,其中的$LINENO是一个shell的内置变量,代表shell脚本的当前行号。
$ cat -n exp1.sh
1 ERRTRAP()
2 {
3 echo "[LINE:$1] Error: Command or function exited with status $?"
4 }
5 foo()
6 {
7 return 1;
8 }
9 trap 'ERRTRAP $LINENO' ERR
10 abc
11 foo
其输出结果如下:
$ sh exp1.sh
exp1.sh: line 10: abc: command not found
[LINE:10] Error: Command or function exited with status 127
[LINE:11] Error: Command or function exited with status 1
在调试过程中,为了跟踪某些变量的值,我们常常需要在shell脚本的许多地方插入相同的echo语句来打印相关变量的值,这种做法显得烦琐而笨拙。
而通过捕获DEBUG信号,我们只需要一条trap语句就可以完成对相关变量的全程跟踪。
以下是一个通过捕获DEBUG信号来跟踪变量的示例程序:
$ cat –n exp2.sh
1 #!/bin/bash
2 trap 'echo “before execute line:$LINENO, a=$a,b=$b,c=$c”' DEBUG
3 a=1
4 if [ "$a" -eq 1 ]
5 then
6 b=2
7 else
8 b=1
9 fi
10 c=3
11 echo "end"
其输出结果如下:
$ sh exp2.sh
before execute line:3, a=,b=,c=
before execute line:4, a=1,b=,c=
before execute line:6, a=1,b=,c=
before execute line:10, a=1,b=2,c=
before execute line:11, a=1,b=2,c=3
end
从运行结果中可以清晰的看到每执行一条命令之后,相关变量的值的变化。
eval
http://www.cnblogs.com/friedwm/archive/2012/04/06/2435171.html
eval 相当于一个参数替换器,它会把所有 $开头的变量 进行求值替换,然后把替换后的结果当作一条命令来执行
#!/bin/bash
PARA="hello world my friend"
function Process()
{
temp=$(eval echo \$$1 | cut -d ' ' -f 2-) #1
eval $1=\$temp #2
}
Process PARA
echo $PARA
[oracle@ ~]$ sh tesh.sh
world my friend
说明:
#1处eval先将它后面所有变量求值,$1==PARA,然后再执行 echo $PARA | cut -d ' ' -f 2-,得到处理后的值,临时存于temp。
#2处,先进行替换,替换结果为: PARA=$temp,再执行这条命令,结果复制回源参数。
http://doudouclever.blog.163.com/blog/static/175112310201252111104169/
set 11 22 33 44
如果要输出最近一个参数,即44,可以使用如下命令,
echo $4
但是如果我们不知道有几个参数的时候,要输出最后一个参数,大家可能会想到使用$#来输出最后一个参数,
如果使用命令:
echo "\$$#"
则得到的结果是 $4,而不是我们想要的44。这里涉及到一个变量间接引用的问题,我们的本意是输出 $4,默认情况下,命令后忽略变量间接引用的情况。
这时候,就可以使用eval命令。
eval echo "\$$#"
得到的结果为44
source、exec与system
http://www.cnblogs.com/zhaoyl/archive/2012/07/07/2580749.html
bash shell的命令分为两类:外部命令和内部命令;
外部命令是通过系统调用或独立的程序实现的,如sed、awk等等;
内部命令是由特殊的文件格式(.def)所实现,如cd、history、exec等等。
有两种方法执行shell scripts,一种是新产生一个shell,然后执行相应的shell scripts;一种是在当前shell下执行,不再启用其他shell。
新产生一个shell然后再执行scripts的方法是在scripts文件开头加入以下语句
#!/bin/sh
一般的script文件(.sh)即是这种用法。这种方法先启用新的sub-shell(新的子进程),然后在其下执行命令。
另外一种方法就是上面说过的source命令,不再产生新的shell,而在当前shell下执行一切命令。
source命令即点(.)命令。
在bash下输入man source,找到source命令解释处,可以看到解释”Read and execute commands from filename in the current shell environment and …”。
从中可以知道,source命令是在当前进程中执行参数文件中的各个命令,而不是另起子进程(或sub-shell)。
exec:
在bash下输入man exec,找到exec命令解释处,可以看到有”No new process is created.”这样的解释,这就是说exec命令不产生新的子进程。那么exec与source的区别是什么呢?
1. 系统调用exec是以新的进程去代替原来的进程,但进程的PID保持不变。因此,可以这样认为,exec系统调用并没有创建新的进程,只是替换了原来进程上下文的内容。
原进程的代码段,数据段,堆栈段被新的进程所代替。
一个进程主要包括以下几个方面的内容:
(1)一个可以执行的程序
(2) 与进程相关联的全部数据(包括变量,内存,缓冲区)
(3)程序上下文(程序计数器PC,保存程序执行的位置)
2. exec是一个函数簇,由6个函数组成,分别是以excl和execv打头的。
执行exec系统调用,一般都是这样,用fork()函数新建立一个进程,然后让进程去执行exec调用。
我们知道,在fork()建立新进程之后,父进各与子进程共享代码段,但数据空间是分开的,但父进程会把自己数据空间的内容copy到子进程中去,还有上下文也会copy到子进程中去。
而为了提高效率,采用一种写时copy的策略,即创建子进程的时候,并不copy父进程的地址空间,父子进程拥有共同的地址空间,
只有当子进程需要写入数据时(如向缓冲区写入数据),这时候会复制地址空间,复制缓冲区到子进程中去。从而父子进程拥有独立的地址空间。
而对于fork()之后执行exec后,这种策略能够很好的提高效率,如果一开始就copy,那么exec之后,子进程的数据会被放弃,被新的进程所代替。
3. exec与system的区别
(1) exec是直接用新的进程去代替原来的程序运行,运行完毕之后不回到原先的程序中去。
(2) system是调用shell执行你的命令,system=fork+exec+waitpid,执行完毕之后,回到原先的程序中去。继续执行下面的部分。
总之,如果你用exec调用,首先应该fork一个新的进程,然后exec. 而system不需要你fork新进程,已经封装好了。
exec命令在执行时会把当前的shell process关闭,然后换到后面的命令继续执行。
感谢各位的阅读!关于“shell知识点有哪些”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。