⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 communications.html

📁 BASH Shell 编程 经典教程 《高级SHELL脚本编程》中文版
💻 HTML
📖 第 1 页 / 共 3 页
字号:
 38&nbsp; 39&nbsp; 40&nbsp;# rsync exclude模式 41&nbsp;# 使用"#"临时注释掉一些不需要的包. 42&nbsp;EXCLUDE=( 43&nbsp;    /1 44&nbsp;    /2 45&nbsp;    /3 46&nbsp;    /testing 47&nbsp;    /4/SRPMS 48&nbsp;    /4/ppc 49&nbsp;    /4/x86_64 50&nbsp;    /4/i386/debug 51&nbsp;   "/4/i386/kde-i18n-*" 52&nbsp;   "/4/i386/openoffice.org-langpack-*" 53&nbsp;   "/4/i386/*i586.rpm" 54&nbsp;   "/4/i386/GFS-*" 55&nbsp;   "/4/i386/cman-*" 56&nbsp;   "/4/i386/dlm-*" 57&nbsp;   "/4/i386/gnbd-*" 58&nbsp;   "/4/i386/kernel-smp*" 59&nbsp;#  "/4/i386/kernel-xen*"  60&nbsp;#  "/4/i386/xen-*"  61&nbsp;) 62&nbsp; 63&nbsp; 64&nbsp;init () { 65&nbsp;    # 让管道命令返回可能的rsync错误, 比如, 网络延时(stalled network). 66&nbsp;    set -o pipefail 67&nbsp; 68&nbsp;    TMP=${TMPDIR:-/tmp}/${0##*/}.$$     # 保存精炼的下载列表. 69&nbsp;    trap "{                                                    70&nbsp;        rm -f $TMP 2&#62;/dev/null                                 71&nbsp;    }" EXIT                             # 删除存在的临时文件. 72&nbsp;} 73&nbsp; 74&nbsp; 75&nbsp;check_pid () { 76&nbsp;# 检查进程是否存在.  77&nbsp;    if [ -s "$PID_FILE" ]; then 78&nbsp;        echo "PID file exists. Checking ..." 79&nbsp;        PID=$(/bin/egrep -o "^[[:digit:]]+" $PID_FILE) 80&nbsp;        if /bin/ps --pid $PID &#38;&#62;/dev/null; then 81&nbsp;            echo "Process $PID found. ${0##*/} seems to be running!" 82&nbsp;           /usr/bin/logger -t ${0##*/} \ 83&nbsp;                 "Process $PID found. ${0##*/} seems to be running!" 84&nbsp;            exit $E_RETURN 85&nbsp;        fi 86&nbsp;        echo "Process $PID not found. Start new process . . ." 87&nbsp;    fi 88&nbsp;} 89&nbsp; 90&nbsp; 91&nbsp;#  根据上边的模式, 92&nbsp;#+ 设置整个文件的更新范围, 从root或$URL开始. 93&nbsp;set_range () { 94&nbsp;    include= 95&nbsp;    exclude= 96&nbsp;    for p in "${INCLUDE[@]}"; do 97&nbsp;        include="$include --include \"$p\"" 98&nbsp;    done 99&nbsp;100&nbsp;    for p in "${EXCLUDE[@]}"; do101&nbsp;        exclude="$exclude --exclude \"$p\""102&nbsp;    done103&nbsp;}104&nbsp;105&nbsp;106&nbsp;# 获得并提炼rsync更新列表.107&nbsp;get_list () {108&nbsp;    echo $$ &#62; $PID_FILE || {109&nbsp;        echo "Can't write to pid file $PID_FILE"110&nbsp;        exit $E_RETURN111&nbsp;    }112&nbsp;113&nbsp;    echo -n "Retrieving and refining update list . . ."114&nbsp;115&nbsp;    # 获得列表 -- 作为单个命令来运行rsync的话需要'eval'.116&nbsp;    # $3和$4是文件创建的日期和时间.117&nbsp;    # $5是完整的包名字.118&nbsp;    previous=119&nbsp;    pre_file=120&nbsp;    pre_date=0121&nbsp;    eval /bin/nice /usr/bin/rsync \122&nbsp;        -r $include $exclude $URL | \123&nbsp;        egrep '^dr.x|^-r' | \124&nbsp;        awk '{print $3, $4, $5}' | \125&nbsp;        sort -k3 | \126&nbsp;        { while read line; do127&nbsp;            # 获得这段运行的秒数, 过滤掉不用的包. 128&nbsp;            cur_date=$(date -d "$(echo $line | awk '{print $1, $2}')" +%s)129&nbsp;            #  echo $cur_date130&nbsp;131&nbsp;            # 取得文件名. 132&nbsp;            cur_file=$(echo $line | awk '{print $3}')133&nbsp;            #  echo $cur_file134&nbsp;135&nbsp;            # 如果可能的话, 从文件名中取得rpm的包名字. 136&nbsp;            if [[ $cur_file == *rpm ]]; then137&nbsp;                pkg_name=$(echo $cur_file | sed -r -e \138&nbsp;                    's/(^([^_-]+[_-])+)[[:digit:]]+\..*[_-].*$/\1/')139&nbsp;            else140&nbsp;                pkg_name=141&nbsp;            fi142&nbsp;            # echo $pkg_name143&nbsp;144&nbsp;            if [ -z "$pkg_name" ]; then   #  如果不是一个rpm文件,145&nbsp;                echo $cur_file &#62;&#62; $TMP    #+ 然后添加到下载列表里.146&nbsp;            elif [ "$pkg_name" != "$previous" ]; then   # 发现一个新包.147&nbsp;                echo $pre_file &#62;&#62; $TMP                  # 输出最新的文件.148&nbsp;                previous=$pkg_name                      # 保存当前状态.149&nbsp;                pre_date=$cur_date150&nbsp;                pre_file=$cur_file151&nbsp;            elif [ "$cur_date" -gt "$pre_date" ]; then  #  如果是相同的包, 但是这个包更新一些, 152&nbsp;                pre_date=$cur_date                      #+ 那么就更新最新的. 153&nbsp;                pre_file=$cur_file154&nbsp;            fi155&nbsp;            done156&nbsp;            echo $pre_file &#62;&#62; $TMP                      #  TMP现在包含所有157&nbsp;                                                        #+ 提炼过的列表. 158&nbsp;            # echo "subshell=$BASH_SUBSHELL"159&nbsp;160&nbsp;    }       # 这里的大括号是为了让最后这句"echo $pre_file &#62;&#62; $TMP"161&nbsp;            # 也能与整个循环一起放到同一个子shell ( 1 )中. 162&nbsp;163&nbsp;    RET=$?  # 取得管道命令的返回状态. 164&nbsp;165&nbsp;    [ "$RET" -ne 0 ] &#38;&#38; {166&nbsp;        echo "List retrieving failed with code $RET"167&nbsp;        exit $E_RETURN168&nbsp;    }169&nbsp;170&nbsp;    echo "done"; echo171&nbsp;}172&nbsp;173&nbsp;# 真正的rsync下载部分. 174&nbsp;get_file () {175&nbsp;176&nbsp;    echo "Downloading..."177&nbsp;    /bin/nice /usr/bin/rsync \178&nbsp;        $OPTS \179&nbsp;        --filter "merge,+/ $TMP" \180&nbsp;        --exclude '*'  \181&nbsp;        $URL $DEST     \182&nbsp;        | /usr/bin/tee $LOG183&nbsp;184&nbsp;    RET=$?185&nbsp;186&nbsp;        #  --filter merge,+/ 对于这个目的来说, 这句是至关重要的. 187&nbsp;        #  + 修饰语意为着包含, / 意味着绝对路径. 188&nbsp;        #  然后$TMP中排过序的列表将会包含升序的路径名, 189&nbsp;        #+ 并从"简化的流程"(shortcutting the circuit)中阻止下边的 --exclude '*'. 190&nbsp;191&nbsp;    echo "Done"192&nbsp;193&nbsp;    rm -f $PID_FILE 2&#62;/dev/null194&nbsp;195&nbsp;    return $RET196&nbsp;}197&nbsp;198&nbsp;# -------199&nbsp;# Main200&nbsp;init201&nbsp;check_pid202&nbsp;set_range203&nbsp;get_list204&nbsp;get_file205&nbsp;RET=$?206&nbsp;# -------207&nbsp;208&nbsp;if [ "$RET" -eq 0 ]; then209&nbsp;    /usr/bin/logger -t ${0##*/} "Fedora update mirrored successfully."210&nbsp;else211&nbsp;    /usr/bin/logger -t ${0##*/} "Fedora update mirrored with failure code: $RET"212&nbsp;fi213&nbsp;214&nbsp;exit $RET</PRE></FONT></TD></TR></TABLE><HR></DIV><P>在使用<BCLASS="COMMAND">rcp</B>, <BCLASS="COMMAND">rsync</B>,	      还有另外一些有安全问题的类似工具的时候, 一定要小心, 因为将这些工具用在shell脚本中是不明智的. 	      你应该考虑使用<BCLASS="COMMAND">ssh</B>, <BCLASS="COMMAND">scp</B>,	      或者<BCLASS="COMMAND">expect</B>脚本来代替这些不安全的工具. </P></DD><DT><ANAME="SSHREF"></A><BCLASS="COMMAND">ssh</B></DT><DD><P><TTCLASS="REPLACEABLE"><I>安全shell</I></TT>, 			  登陆远端主机并在其上运行命令. 			  这个工具具有身份认证和加密的功能, 			  可以安全的替换<BCLASS="COMMAND">telnet</B>,			  <BCLASS="COMMAND">rlogin</B>, <BCLASS="COMMAND">rcp</B>, 			  和<BCLASS="COMMAND">rsh</B>等工具. 			  请参考这个工具的<EM>man页</EM>来获取详细信息. 	      </P><DIVCLASS="EXAMPLE"><HR><ANAME="REMOTE"></A><P><B>例子 12-40. 使用ssh</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/bash  2&nbsp;# remote.bash: 使用ssh.   3&nbsp;  4&nbsp;# 这个例子是Michael Zick编写的.   5&nbsp;# 授权在本书中使用.   6&nbsp;  7&nbsp;  8&nbsp;#   假设的一些前提:  9&nbsp;#   --------------- 10&nbsp;#   fd-2(文件描述符2)的内容并没有被丢弃( '2&#62;/dev/null' ). 11&nbsp;#   ssh/sshd假设stderr ('2')将会显示给用户.  12&nbsp;# 13&nbsp;#   假设sshd正运行在你的机器上.  14&nbsp;#   对于绝大多数'标准'的发行版, 都是有sshd的,  15&nbsp;#+  并且没有稀奇古怪的ssh-keygen.  16&nbsp; 17&nbsp;# 在你的机器上从命令行中试着运行一下ssh: 18&nbsp;# 19&nbsp;# $ ssh $HOSTNAME 20&nbsp;# 不需要特别的设置, 也会要求你输入密码.  21&nbsp;#   接下来输入密码,  22&nbsp;#   完成后, $ exit 23&nbsp;# 24&nbsp;# 能够正常运行么? 如果正常的话, 接下来你可以获得更多的乐趣了.  25&nbsp; 26&nbsp;# 尝试在你的机器上以'root'身份来运行ssh: 27&nbsp;# 28&nbsp;#   $  ssh -l root $HOSTNAME 29&nbsp;#   当要求询问密码时, 输入root的密码, 注意别输入你的用户密码.  30&nbsp;#          Last login: Tue Aug 10 20:25:49 2004 from localhost.localdomain 31&nbsp;#   完成后键入'exit'. 32&nbsp; 33&nbsp;#  上边的动作将会带给你一个交互的shell.  34&nbsp;#  也可以在'single command'模式下建立sshd,  35&nbsp;#+ 但是这已经超出本例所讲解的范围了.  36&nbsp;#  唯一需要注意的是, 下面的命令都可以运行在 37&nbsp;#+ 'single command'模式下. 38&nbsp; 39&nbsp; 40&nbsp;# 基本的, 写stdout(本地)命令. 41&nbsp; 42&nbsp;ls -l 43&nbsp; 44&nbsp;# 这样远端机器上就会执行相同的命令.  45&nbsp;# 如果你想的话, 可以传递不同的'USERNAME'和'HOSTNAME':  46&nbsp;USER=${USERNAME:-$(whoami)} 47&nbsp;HOST=${HOSTNAME:-$(hostname)} 48&nbsp; 49&nbsp;#  现在, 在远端主机上执行上边的命令,  50&nbsp;#+ 当然, 所有的传输都会被加密. 51&nbsp; 52&nbsp;ssh -l ${USER} ${HOST} " ls -l " 53&nbsp; 54&nbsp;#  期望的结果就是在远端主机上列出 55&nbsp;#+ 你的用户名所拥有的主目录下的所有文件.  56&nbsp;#  如果想看点不一样的东西,  57&nbsp;#+ 那就在别的地方运行这个脚本, 别在你自己的主目录下运行这个脚本.  58&nbsp; 59&nbsp;#  换句话说, Bash命令已经作为一个引用行 60&nbsp;#+ 被传递到了远端shell中, 这样远端机器就会运行它.  61&nbsp;#  在这种情况下, sshd代表你运行了' bash -c "ls -l" '. 62&nbsp; 63&nbsp;#  如果你想不输入密码,  64&nbsp;#+ 或者想更详细的了解相关的问题, 请参考:  65&nbsp;#+    man ssh 66&nbsp;#+    man ssh-keygen 67&nbsp;#+    man sshd_config. 68&nbsp; 69&nbsp;exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><DIVCLASS="CAUTION"><P></P><TABLECLASS="CAUTION"WIDTH="90%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="./images/caution.gif"HSPACE="5"ALT="Caution"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>在循环中, <BCLASS="COMMAND">ssh</B>可能会引起一些异常问题. 		根据comp.unix上的shell文档<AHREF="http://groups-beta.google.com/group/comp.unix.shell/msg/dcb446b5fff7d230"TARGET="_top">		Usenet post</A>所描述的内容, 	<BCLASS="COMMAND">ssh</B>继承了循环的<TTCLASS="FILENAME">stdin</TT>. 	为了解决这个问题, 		请使用<BCLASS="COMMAND">ssh</B>的<CODECLASS="OPTION">-n</CODE>或者<CODECLASS="OPTION">-f</CODE>选项. </P><P>感谢, Jason Bechtel, 为我们指出这个问题. </P></TD></TR></TABLE></DIV></DD><DT><BCLASS="COMMAND">scp</B></DT><DD><P><TTCLASS="REPLACEABLE"><I>安全拷贝</I></TT>, 			  在功能上与<BCLASS="COMMAND">rcp</B>很相似, 			  就是在两个不同的网络主机之间拷贝文件, 	      但是要使用鉴权的方式, 并且要使用与<BCLASS="COMMAND">ssh</B>类似的安全层. </P></DD></DL></DIV><P></P><DIVCLASS="VARIABLELIST"><P><B><ANAME="COMMLOCAL1"></A>本地网络</B></P><DL><DT><ANAME="WRITEREF"></A><BCLASS="COMMAND">write</B></DT><DD><P>这是一个端到端通讯的工具. 	      这个工具可以从你的终端上(console或者<ICLASS="FIRSTTERM">xterm</I>)发送整行数据到另一个用户的终端上. 	      <AHREF="system.html#MESGREF">mesg</A>命令当然也可以用来禁用对于一个终端的写权限. </P><P>因为<BCLASS="COMMAND">write</B>命令是需要交互的, 		  所以这个命令在脚本中很少使用. </P></DD><DT><BCLASS="COMMAND">netconfig</B></DT><DD><P>用来配置网络适配器(使用DHCP)的命令行工具. 	      这个命令对于红帽发行版来说是内置的. 	      </P></DD></DL></DIV><P></P><DIVCLASS="VARIABLELIST"><P><B><ANAME="COMMMAIL1"></A>Mail</B></P><DL><DT><BCLASS="COMMAND">mail</B></DT><DD><P>发送或者读取e-mail消息. </P><P>如果把这个命令行的mail客户端当成一个脚本中的命令来使用的话, 效果非常好. </P><DIVCLASS="EXAMPLE"><HR><ANAME="SELFMAILER"></A><P><B>例子 12-41. 一个mail自身的脚本</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING">  1&nbsp;#!/bin/sh  2&nbsp;# self-mailer.sh: mail自身的脚本.   3&nbsp;  4&nbsp;adr=${1:-`whoami`}     # 如果没有指定的话, 默认是当前用户.  5&nbsp;#  键入'self-mailer.sh wiseguy@superdupergenius.com'  6&nbsp;#+ 将脚本发送到这个地址.   7&nbsp;#  如果只键入'self-mailer.sh'(不给参数)的话,   8&nbsp;#+ 那么这个脚本就会被发送给调用者, 比如, 比如, bozo@localhost.localdomain.  9&nbsp;# 10&nbsp;#  如果想了解${parameter:-default}结构的更多细节,  11&nbsp;#+ 请参考"变量重游"那章中的 12&nbsp;#+ "参数替换"小节.  13&nbsp; 14&nbsp;# ============================================================================ 15&nbsp;  cat $0 | mail -s "Script \"`basename $0`\" has mailed itself to you." "$adr" 16&nbsp;# ============================================================================ 17&nbsp; 18&nbsp;# -------------------------------------------- 19&nbsp;#  来自self-mailing脚本的一份祝福.  20&nbsp;#  一个喜欢恶搞的家伙运行了这个脚本,  21&nbsp;#+ 这导致了他自己收到了这份mail.  22&nbsp;#  显然的, 有些人确实没什么事好做,  23&nbsp;#+ 就只能浪费他们自己的时间玩了.  24&nbsp;# -------------------------------------------- 25&nbsp; 26&nbsp;echo "At `date`, script \"`basename $0`\" mailed to "$adr"." 27&nbsp; 28&nbsp;exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV></DD><DT><BCLASS="COMMAND">mailto</B></DT><DD><P>与<BCLASS="COMMAND">mail</B>命令很相似, 	      <BCLASS="COMMAND">mailto</B>可以使用命令行或在脚本中发送e-mail消息. 	      而且<BCLASS="COMMAND">mailto</B>也可以发送MIME(多媒体)消息. </P></DD><DT><BCLASS="COMMAND">vacation</B></DT><DD><P>这个工具可以自动回复e-mail给发送者, 	      表示邮件的接受者正在度假暂时无法收到邮件. 		  这个工具与<BCLASS="COMMAND">sendmail</B>一起运行于网络上, 		  并且这个工具不支持拨号的POPmail帐号. </P></DD></DL></DIV></DIV><H3CLASS="FOOTNOTES">注意事项</H3><TABLEBORDER="0"CLASS="FOOTNOTES"WIDTH="100%"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="5%"><ANAME="FTN.AEN9898"HREF="communications.html#AEN9898"><SPANCLASS="footnote">[1]</SPAN></A></TD><TDALIGN="LEFT"VALIGN="TOP"WIDTH="95%"><P><ANAME="DAEMONREF"></A></P><P>一个<EM>幽灵进程</EM>指的是并未附加在终端会话中的后台进程. 			  幽灵进程在指定的时间执行指定的服务, 			  或者由特定的事件触发来执行指定的服务. 		    </P><P>希腊文中的<SPANCLASS="QUOTE">"daemon"</SPAN>意思是幽灵, 			  这个词充满了神秘感和神奇的力量, 			  在UNIX中幽灵进程总是在后台默默地执行着分配给它们的任务. 		    </P></TD></TR></TABLE><DIVCLASS="NAVFOOTER"><HRALIGN="LEFT"WIDTH="100%"><TABLESUMMARY="Footer navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top"><AHREF="filearchiv.html"ACCESSKEY="P">前一页</A></TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="index.html"ACCESSKEY="H">首页</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top"><AHREF="terminalccmds.html"ACCESSKEY="N">下一页</A></TD></TR><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top">文件与归档命令</TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="external.html"ACCESSKEY="U">上一级</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top">终端控制命令</TD></TR></TABLE></DIV></BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -