extmisc.html
来自「BASH Shell 编程 经典教程 《高级SHELL脚本编程》中文版」· HTML 代码 · 共 2,164 行 · 第 1/3 页
HTML
2,164 行
><PRECLASS="SCREEN"><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">printenv | grep HOME</KBD><SAMPCLASS="COMPUTEROUTPUT">HOME=/home/bozo</SAMP> </PRE></FONT></TD></TR></TABLE> </P></DD><DT><BCLASS="COMMAND">lp</B></DT><DD><P><BCLASS="COMMAND">lp</B>和<BCLASS="COMMAND">lpr</B>命令将会把文件发送到打印队列中, 并且作为硬拷贝来打印. <ANAME="AEN10624"HREF="#FTN.AEN10624"><SPANCLASS="footnote">[2]</SPAN></A> 这些命令会记录它们名字的起点, 直到行打印机的另一个阶段. </P><P><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">lp file1.txt</KBD> 或者 <SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">lp <file1.txt</KBD></P><P>通常情况下都是将<BCLASS="COMMAND">pr</B>的格式化输出传递到<BCLASS="COMMAND">lp</B>中. </P><P><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">pr -options file1.txt | lp</KBD> </P><P>格式化的包, 比如<BCLASS="COMMAND">groff</B>和<EM>Ghostscript</EM>就可以将它们的输出直接发送给<BCLASS="COMMAND">lp</B>. </P><P><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">groff -Tascii file.tr | lp</KBD> </P><P><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">gs -options | lp file.ps</KBD> </P><P>还有一些相关的命令, 比如<BCLASS="COMMAND">lpq</B>, 可以用来查看打印队列, 而<BCLASS="COMMAND">lprm</B>, 可以从打印队列中删除作业. </P></DD><DT><ANAME="TEEREF"></A><BCLASS="COMMAND">tee</B></DT><DD><P>[这是UNIX从管道行业借来的主意.]</P><P>这是一个重定向操作, 但是与之前所看到的有点不同. 就像管道中的<SPANCLASS="QUOTE">"三通"</SPAN>一样, 这个命令可以将命令或者管道命令的输出<SPANCLASS="QUOTE">"抽出"</SPAN>到<EM>一个文件</EM>中, 而且不影响结果. 当你想将一个运行中进程的输出保存到文件时, 或者为了debug而保存输出记录的时候, 这个命令就显得非常有用了. </P><TABLEBORDER="1"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="SCREEN"> (重定向) |----> 到文件 | ==========================|==================== 命令 ---> 命令 ---> |tee ---> 命令 ---> ---> 管道的输出 =============================================== </PRE></FONT></TD></TR></TABLE><P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 cat listfile* | sort | tee check.file | uniq > result.file</PRE></FONT></TD></TR></TABLE> (在对排序的结果进行<AHREF="textproc.html#UNIQREF">uniq</A>(去掉重复行)之前, 文件<TTCLASS="FILENAME">check.file</TT>保存了排过序的<SPANCLASS="QUOTE">"listfiles"</SPAN>. )</P></DD><DT><BCLASS="COMMAND">mkfifo</B></DT><DD><P><ANAME="NAMEDPIPEREF"></A>这个不大引人注意的命令可以创建一个<EM>命名管道</EM>, 并产生一个临时的<EM>先进先出的buffer</EM>, 用来在两个进程之间传递数据. <ANAME="AEN10686"HREF="#FTN.AEN10686"><SPANCLASS="footnote">[3]</SPAN></A> 典型的应用是一个进程向FIFO中写数据, 另一个进程读出来. 请参考<AHREF="contributed-scripts.html#FIFO">例子 A-15</A>. </P></DD><DT><BCLASS="COMMAND">pathchk</B></DT><DD><P>这个命令用来检查文件名的有效性. 如果文件名超过了最大允许长度(255个字符), 或者它所在的一个或多个路径搜索不到, 那么就会产生一个错误结果. </P><P>不幸的是, <BCLASS="COMMAND">pathchk</B>并不能够返回一个可识别的错误码, 因此它在脚本中几乎没有什么用. 可以考虑使用<AHREF="fto.html#RTIF">文件测试操作</A>来替代这个命令. </P></DD><DT><ANAME="DDREF"></A><BCLASS="COMMAND">dd</B></DT><DD><P>这也是一个不太出名的工具, 但却是一个令人恐惧的<SPANCLASS="QUOTE">"数据复制"</SPAN>命令. 最开始, 这个命令被用来在UNIX微机和IBM大型机之间通过磁带来交换数据, 这个命令现在仍然有它的用途. <BCLASS="COMMAND">dd</B>命令只不过是简单的拷贝一个文件(或者<TTCLASS="FILENAME">stdin/stdout</TT>), 但是它会做一些转换. 下边是一些可能的转换, 比如 ASCII/EBCDIC, <ANAME="AEN10719"HREF="#FTN.AEN10719"><SPANCLASS="footnote">[4]</SPAN></A> 大写/小写, 在输入和输出之间的字节对的交换, 还有对输入文件做一些截头去尾的工作. <KBDCLASS="USERINPUT">dd --help</KBD>列出了所有转换, 还列出了这个强大工具的其他一些选项. </P><P> <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 # 将一个文件转换为大写: 2 3 dd if=$filename conv=ucase > $filename.uppercase 4 # lcase # 转换为小写</PRE></FONT></TD></TR></TABLE> </P><DIVCLASS="EXAMPLE"><HR><ANAME="SELFCOPY"></A><P><B>例子 12-52. 一个拷贝自身的脚本</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # self-copy.sh 3 4 # 这个脚本会拷贝自身. 5 6 file_subscript=copy 7 8 dd if=$0 of=$0.$file_subscript 2>/dev/null 9 # 阻止dd产生的消息: ^^^^^^^^^^^ 10 11 exit $?</PRE></FONT></TD></TR></TABLE><HR></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="EXERCISINGDD"></A><P><B>例子 12-53. 练习<BCLASS="COMMAND">dd</B></B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # exercising-dd.sh 3 4 # 由Stephane Chazelas编写. 5 # 本文作者做了少量修改. 6 7 input_file=$0 # 脚本自身. 8 output_file=log.txt 9 n=3 10 p=5 11 12 dd if=$input_file of=$output_file bs=1 skip=$((n-1)) count=$((p-n+1)) 2> /dev/null 13 # 从脚本中把位置n到p的字符提取出来. 14 15 # ------------------------------------------------------- 16 17 echo -n "hello world" | dd cbs=1 conv=unblock 2> /dev/null 18 # 垂直地echo "hello world". 19 20 exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><P>为了展示<BCLASS="COMMAND">dd</B>的多种用途, 让我们使用它来记录按键. </P><DIVCLASS="EXAMPLE"><HR><ANAME="DDKEYPRESS"></A><P><B>例子 12-54. 记录按键</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # dd-keypress.sh: 记录按键, 不需要按回车. 3 4 5 keypresses=4 # 记录按键的个数. 6 7 8 old_tty_setting=$(stty -g) # 保存旧的终端设置. 9 10 echo "Press $keypresses keys." 11 stty -icanon -echo # 禁用标准模式. 12 # 禁用本地echo. 13 keys=$(dd bs=1 count=$keypresses 2> /dev/null) 14 # 如果不指定输入文件的话, 'dd'使用标准输入. 15 16 stty "$old_tty_setting" # 恢复旧的终端设置. 17 18 echo "You pressed the \"$keys\" keys." 19 20 # 感谢Stephane Chazelas, 演示了这种方法. 21 exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><P><BCLASS="COMMAND">dd</B>命令可以在数据流上做随机访问. <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 echo -n . | dd bs=1 seek=4 of=file conv=notrunc 2 # "conv=notrunc"选项意味着输出文件不能被截短. 3 4 # 感谢, S.C.</PRE></FONT></TD></TR></TABLE> </P><P><BCLASS="COMMAND">dd</B>命令可以将数据或磁盘镜像拷贝到设备中, 也可以从设备中拷贝数据或磁盘镜像, 比如说磁盘或磁带设备都可以(<AHREF="contributed-scripts.html#COPYCD">例子 A-5</A>). 通常用来创建启动磁盘. </P><P> <KBDCLASS="USERINPUT">dd if=kernel-image of=/dev/fd0H1440</KBD> </P><P>同样的, <BCLASS="COMMAND">dd</B>可以拷贝软盘的整个内容(甚至是<SPANCLASS="QUOTE">"其他"</SPAN>操作系统的磁盘格式), 到硬盘驱动器上(以镜像文件的形式). </P><P> <KBDCLASS="USERINPUT">dd if=/dev/fd0 of=/home/bozo/projects/floppy.img</KBD> </P><P> <BCLASS="COMMAND">dd</B>命令还有一些其他用途, 包括可以初始化临时交换文件(<AHREF="zeros.html#EX73">例子 28-2</A>)和ramdisks(内存虚拟硬盘)(<AHREF="zeros.html#RAMDISK">例子 28-3</A>). 它甚至可以做一些对整个硬盘分区的底层拷贝, 虽然不建议这么做. </P><P>某些(可能是比较无聊的)人总会想一些关于<BCLASS="COMMAND">dd</B>命令的有趣应用. </P><DIVCLASS="EXAMPLE"><HR><ANAME="BLOTOUT"></A><P><B>例子 12-55. 安全的删除一个文件</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # blot-out.sh: 删除一个文件"所有"的记录. 3 4 # 这个脚本会使用随机字节交替的覆盖目标文件, 5 #+ 并且在最终删除这个文件之前清零. 6 # 这么做之后, 即使你通过传统手段来检查磁盘扇区 7 #+ 也不能把文件原始数据重新恢复. 8 9 PASSES=7 # 破坏文件的次数. 10 # 提高这个数字会减慢脚本运行的速度, 11 #+ 尤其是对尺寸比较大的目标文件进行操作的时候. 12 BLOCKSIZE=1 # 带有/dev/urandom的I/O需要单位块尺寸, 13 #+ 否则你可能会获得奇怪的结果. 14 E_BADARGS=70 # 不同的错误退出码. 15 E_NOT_FOUND=71 16 E_CHANGED_MIND=72 17 18 if [ -z "$1" ] # 没指定文件名. 19 then 20 echo "Usage: `basename $0` filename" 21 exit $E_BADARGS 22 fi 23 24 file=$1 25 26 if [ ! -e "$file" ] 27 then 28 echo "File \"$file\" not found." 29 exit $E_NOT_FOUND 30 fi 31 32 echo; echo -n "Are you absolutely sure you want to blot out \"$file\" (y/n)? " 33 read answer 34 case "$answer" in 35 [nN]) echo "Changed your mind, huh?" 36 exit $E_CHANGED_MIND 37 ;; 38 *) echo "Blotting out file \"$file\".";; 39 esac 40 41 42 flength=$(ls -l "$file" | awk '{print $5}') # 5是文件长度. 43 pass_count=1 44 45 chmod u+w "$file" # 允许覆盖/删除这个文件. 46 47 echo 48 49 while [ "$pass_count" -le "$PASSES" ] 50 do 51 echo "Pass #$pass_count" 52 sync # 刷新buffers. 53 dd if=/dev/urandom of=$file bs=$BLOCKSIZE count=$flength 54 # 使用随机字节进行填充. 55 sync # 再次刷新buffer. 56 dd if=/dev/zero of=$file bs=$BLOCKSIZE count=$flength 57 # 用0填充. 58 sync # 再次刷新buffer. 59 let "pass_count += 1" 60 echo 61 done 62 63 64 rm -f $file # 最后, 删除这个已经被破坏得不成样子的文件. 65 sync # 最后一次刷新buffer. 66 67 echo "File \"$file\" blotted out and deleted."; echo 68 69 70 exit 0 71 72 # 这是一种真正安全的删除文件的办法, 73 #+ 但是效率比较低, 运行比较慢. 74 # GNU文件工具包中的"shred"命令, 75 #+ 也可以完成相同的工作, 不过更有效率. 76 77 # 使用普通的方法是不可能重新恢复这个文件了. 78 # 然而 . . . 79 #+ 这个简单的例子是不能够抵抗 80 #+ 那些经验丰富并且正规的分析. 81 82 # 这个脚本可能不会很好的运行在日志文件系统上(JFS). 83 # 练习 (很难): 像它做的那样修正这个问题. 84 85 86 87 # Tom Vier的文件删除包可以更加彻底的删除文件, 88 #+ 比这个例子厉害的多. 89 # http://www.ibiblio.org/pub/Linux/utils/file/wipe-2.0.0.tar.bz2 90 91 # 如果想对安全删除文件这一论题进行深入的分析, 92 #+ 可以参见Peter Gutmann的网页, 93 #+ "Secure Deletion of Data From Magnetic and Solid-State Memory". 94 # http://www.cs.auckland.ac.nz/~pgut001/pubs/secure_del.html</PRE></FONT></TD></TR></TABLE><HR></DIV></DD><DT><ANAME="ODREF"></A><BCLASS="COMMAND">od</B></DT><DD><P><BCLASS="COMMAND">od</B>, 或者<EM>octal dump</EM>过滤器, 将会把输入(或文件)转换为8进制或者其他进制. 在你需要查看或处理一些二进制数据文件或者一个不可读的系统设备文件的时候, 这个命令非常有用, 比如<TTCLASS="FILENAME">/dev/urandom</TT>, 或者是一个二进制数据过滤器. 请参考<AHREF="randomvar.html#SEEDINGRANDOM">例子 9-29</A>和<AHREF="textproc.html#RND">例子 12-13</A>. </P></DD><DT><BCLASS="COMMAND">hexdump</B></DT><DD><P>对二进制文件进行 16进制, 8进制, 10进制, 或者ASCII码的查阅动作. 这个命令大体上与上边的<BCLASS="COMMAND">od</B>命令的作用相同, 但是远没有<BCLASS="COMMAND">od</B>命令有用. </P></DD><DT><BCLASS="COMMAND">objdump</B></DT><DD><P>显示编译后的二进制文件或二进制可执行文件的信息, 以16进制的形式显示, 或者显示反汇编列表(使用<CODECLASS="OPTION">-d</CODE>选项). </P><P> <TABLEBORDER="1"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="SCREEN"><SAMPCLASS="PROMPT"
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?