十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
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 | 正常范围之外的退出状态码 |
举例说明:
默认情况下,shell脚本会以脚本中的最后一个命令的退出状态码退出。
使用exit命令可以改变这种行为,允许你在脚本结束时指定一个退出状态码。
退出状态码是一个0~255的整数,参数太大,会被系统取模。
环境变量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_old=$IFS
IFS=$'\n'
<使用新的IFS值>
IFS=$IFS_old
这就保证了在脚本的后续操作中使用的是IFS的默认值。建议在任何时候都这么做。
要指定多个IFS字符,只要将它们在赋值行串起来就行了:
IFS=$'\n':;"
这里将换行符、冒号、分号、双引号作为字段分隔符。
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
$
利用这个方法,既能将数据保存在文件中,也能将数据显示在屏幕上。这样就可以在为用户显示输出的同时再永久保存一份输出的内容了。
创建文件,在这之后输入任何内容都是在文件里的。输入完成之后EOF结尾,代表结束:
$ cat > test << EOF
> line 1,
> Line 2;
> LINE 3.
> EOF
$ cat test
line 1,
Line 2;
LINE 3.
$
输出重定向将cat命令的输出写入文件(也可以用>>来追加内容)。输入不再取自标准输入,而是被重定向到命令行(或者脚本)之后的内容中。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 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作为老牌的进制查看工具,使用上比较麻烦。且显示方式上不如上面两个工整。