189 8069 5689

shell的退出状态码,IFS环境变量,tee命令,cat>file<<EOF的用法

退出状态码

shell中运行的每个命令都使用退出状态码(exit status)。退出状态码是一个0~255的整数,在命令结束运行时有命令传给shell。

目前创新互联建站已为成百上千的企业提供了网站建设、域名、虚拟主机、网站托管维护、企业网站设计、华容网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。

查看退出状态码

Linux提供了一个专门的变量 $? 来保存上一个已执行命令的退出状态码。对于需要进行检查的命令,必须在其运行完毕后立刻查看或使用 $? 变量。它的值会变成有shell所执行的最后一条命令的退出状态码。

一个成功结束的命令的退出状态码是0。Linux错误退出状态码没有什么标准可循,但有一些可用的参考:

状态码描述
0 命令成功结束
1 一般性未知错误
2 不适合的shell指令
126 命令不可执行
127 没找到命令
128 无效的退出参数
128+x 与Linux信号x相关的严重错误
130 通过 Ctrl+C 终止的命令
255 正常范围之外的退出状态码

举例说明:

  • 无效的命令会返回一个退出状态码127。
  • 退出状态码126,表明用户没有执行命令的正确权限。
  • 给命令提供了无效参数,会产生一般性的退出状态码1,表明在命令中发生了未知错误。

exit 命令

默认情况下,shell脚本会以脚本中的最后一个命令的退出状态码退出。
使用exit命令可以改变这种行为,允许你在脚本结束时指定一个退出状态码。

退出状态码是一个0~255的整数,参数太大,会被系统取模。

IFS 字段分隔符

环境变量IFS,叫做内部字段分隔符(internal field separator)。IFS环境变量定义了bash shell用作字段分隔符的一些列字符。默认情况下是空格、制表符、换行符。可以更改这个环境变量。
因为都是一些特殊字符,直接输出是看不到的:

$ echo "$IFS"

$ echo "$IFS" | od -b
0000000 040 011 012 012
0000004
$ 

这里转成了八进制。"040"是空格,"011"是制表符,"012"是换行符 。最后一个 012 是因为 echo 默认是会换行的。
还可以试一下 -c 选项,这样会打印出 \t 和 \n 但是空格还是空格,就不明显了。

od命令
od命令系统默认的显示方式是八进制,名称源于Octal Dump。另外还有一个hexdump命令,以十六进制输出。功能上应该有一些差别,用起来差不多,这里的情况把od命令替换为hexdump命令的效果应该是一样的。
hexdump有个-C(大写)选项是od没有的,这里没什么效果,用来查看文件的时候效果好。

只识别换行符:

IFS=$'\n'

临时更改IFS

一个可参考的安全实践是在改变IFS之前保存原来的值,之后再恢复它:

IFS_old=$IFS
IFS=$'\n'
<使用新的IFS值>
IFS=$IFS_old

这就保证了在脚本的后续操作中使用的是IFS的默认值。建议在任何时候都这么做。

指定多个IFS字符

要指定多个IFS字符,只要将它们在赋值行串起来就行了:

IFS=$'\n':;"

这里将换行符、冒号、分号、双引号作为字段分隔符。

tee 将输出同时发送到屏幕和文件

tee命令相当于管道的一个T型接头。它将从STDIN过来的数据同时发往两处。一处是STDOUT,另一处是tee命令行所指定的文件名。

默认情况下,每次都会覆盖文件:

$ date | tee test1
Fri Dec  6 16:32:59 CST 2019
$ cat test1
Fri Dec  6 16:32:59 CST 2019
$ date | tee test1
Fri Dec  6 16:33:10 CST 2019
$ cat test1
Fri Dec  6 16:33:10 CST 2019
$ 

如果想追加数据,需要用-a选项:

$ cat test1
Fri Dec  6 16:33:10 CST 2019
$ date | tee -a test1
Fri Dec  6 16:34:00 CST 2019
$ cat test1
Fri Dec  6 16:33:10 CST 2019
Fri Dec  6 16:34:00 CST 2019
$ 

利用这个方法,既能将数据保存在文件中,也能将数据显示在屏幕上。这样就可以在为用户显示输出的同时再永久保存一份输出的内容了。

cat > file << EOF 的用法

创建文件,在这之后输入任何内容都是在文件里的。输入完成之后EOF结尾,代表结束:

$ cat > test << EOF
> line 1,
> Line 2;
> LINE 3.
> EOF
$ cat test
line 1,
Line 2;
LINE 3.
$ 

输出重定向将cat命令的输出写入文件(也可以用>>来追加内容)。输入不再取自标准输入,而是被重定向到命令行(或者脚本)之后的内容中。EOF符号标记了追加到文件中的数据的结束。
使用这个命令,在脚本中创建一个文件并写入多行内容就很方便,

<<- EOF

使用EOF表示结束的时候,必须要顶格写,否则不认。如果在脚本中使用,有时候希望代码块有缩进。这时候就可以用这个:

If the redirection operator is <<-, then all leading tab characters are stripped from input lines and the line containing delimiter.
如果重定向的操作符是<<-,那么分界符(EOF)所在行的开头部分的制表符(Tab)都将被去除。

不过这个只会忽略制表符,如果用空格缩进还是用不上。

永久重定向

如果有大量的语句需要重定向,在每条命令后面都指定是相当麻烦的。
下面的命令是,git放弃修改,强制覆盖本地代码:

git fetch --all && git reset --hard origin/master && git pull

即时合并成一行,这里也是3天命令。如果要将输出重定向,仅仅在最后加上,则只会重定向最后一条命令的输出。

exec 命令

exec命令的效果是不产生新的子进程,所以不是做永久重定向的,但是靠这个命令能实现永久重定向。命令具体的效果是什么在这里不重要。

exec 1>/dev/null
git fetch --all && git reset --hard origin/master && git pull

这样,在exec命令之后,所有的语句就都会重定向到指定的地方。
问题:一定重定向了STDOUT或STDERR,就很难在将它们重定向回原来的位置了。所以如果需要切换回来,重定向前先备份当前的描述符。

重定向文件描述符

可以将STDOUT的原来位置重定向到另外一个文件描述符,然后再利用该文件描述符重定向STDOUT:

exec 3>&1 && exec 1>/dev/null
git fetch --all && git reset --hard origin/master && git pull
exec 1<&3

先将 FD3 指向 STDOUT,指向 FD3 就是指向 STDOUT。然后就可以把 FD1 改了。之后,要再将 FD1 重新指向 STDOUT,指向 FD3 就是指向 STDOUT,所以通过 FD3 就又指回去了。

另外,下面的方法效果也是一样的:

exec 4<&1 && exec 1>/dev/null
git fetch --all && git reset --hard origin/master && git pull
exec 1<&4

先将 STDOUT 指向 FD4,这样就把 STDOUT 备份到 FD4了。之后再加备份的 FD4 里的 STDOUT 指回给 FD1。

进制查看工具

有三个命令都可以像UltraEdit那样以16进制的方式查看文件。
hexdump的输入格式最灵活,因为它有专门的参数指定格式, 常用选项 -C。
od没什么特点,od -x 和不带选项的xxd差不多。
xxd还可以通过-r选项把16进制表示的反转换为正常的文件因为它默认的表示方式和UltraEdit最像:以位移开头,然后每两字节一组,每行最后有相应字节的文件显示。

提到linux/unix下的进制查看工具,不得不提到以上的三个工具。
hexdump在使用上和windows下的winhex接近。
xxd可以看作是od的升级产品。且其-r选项把16进制表示的反转换为正常的文件。比较像是ultraedit软件的十六进制查看。
od作为老牌的进制查看工具,使用上比较麻烦。且显示方式上不如上面两个工整。


当前文章:shell的退出状态码,IFS环境变量,tee命令,cat>file<<EOF的用法
文章位置:http://cdxtjz.cn/article/jigiod.html

其他资讯