📄 debugging.html
字号:
><B><ANAME="TRAPREF1"></A>Trapping signals</B></P><DL><DT><BCLASS="COMMAND">trap</B></DT><DD><P>Specifies an action on receipt of a signal; also useful for debugging. <DIVCLASS="NOTE"><TABLECLASS="NOTE"WIDTH="90%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="common/note.png"HSPACE="5"ALT="Note"></TD><TDALIGN="LEFT"VALIGN="TOP"><P><ANAME="SIGNALD"></A>A <ICLASS="FIRSTTERM">signal</I> is simply a message sent to a process, either by the kernel or another process, telling it to take some specified action (usually to terminate). For example, hitting a <BCLASS="KEYCAP">Control</B>-<BCLASS="KEYCAP">C</B>, sends a user interrupt, an INT signal, to a running program.</P></TD></TR></TABLE></DIV> <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 trap '' 2 2 # Ignore interrupt 2 (Control-C), with no action specified. 3 4 trap 'echo "Control-C disabled."' 2 5 # Message when Control-C pressed.</PRE></TD></TR></TABLE> </P></DD></DL></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="EX76"></A><P><B>Example 29-5. Trapping at exit</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # Hunting variables with a trap. 3 4 trap 'echo Variable Listing --- a = $a b = $b' EXIT 5 # EXIT is the name of the signal generated upon exit from a script. 6 # 7 # The command specified by the "trap" doesn't execute until 8 #+ the appropriate signal is sent. 9 10 echo "This prints before the \"trap\" --" 11 echo "even though the script sees the \"trap\" first." 12 echo 13 14 a=39 15 16 b=36 17 18 exit 0 19 # Note that commenting out the 'exit' command makes no difference, 20 #+ since the script exits in any case after running out of commands.</PRE></TD></TR></TABLE><HR></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="ONLINE"></A><P><B>Example 29-6. Cleaning up after <BCLASS="KEYCAP">Control-C</B></B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # logon.sh: A quick 'n dirty script to check whether you are on-line yet. 3 4 umask 177 # Make sure temp files are not world readable. 5 6 7 TRUE=1 8 LOGFILE=/var/log/messages 9 # Note that $LOGFILE must be readable 10 #+ (as root, chmod 644 /var/log/messages). 11 TEMPFILE=temp.$$ 12 # Create a "unique" temp file name, using process id of the script. 13 # Using 'mktemp' is an alternative. 14 # For example: 15 # TEMPFILE=`mktemp temp.XXXXXX` 16 KEYWORD=address 17 # At logon, the line "remote IP address xxx.xxx.xxx.xxx" 18 # appended to /var/log/messages. 19 ONLINE=22 20 USER_INTERRUPT=13 21 CHECK_LINES=100 22 # How many lines in log file to check. 23 24 trap 'rm -f $TEMPFILE; exit $USER_INTERRUPT' TERM INT 25 # Cleans up the temp file if script interrupted by control-c. 26 27 echo 28 29 while [ $TRUE ] #Endless loop. 30 do 31 tail -n $CHECK_LINES $LOGFILE> $TEMPFILE 32 # Saves last 100 lines of system log file as temp file. 33 # Necessary, since newer kernels generate many log messages at log on. 34 search=`grep $KEYWORD $TEMPFILE` 35 # Checks for presence of the "IP address" phrase, 36 #+ indicating a successful logon. 37 38 if [ ! -z "$search" ] # Quotes necessary because of possible spaces. 39 then 40 echo "On-line" 41 rm -f $TEMPFILE # Clean up temp file. 42 exit $ONLINE 43 else 44 echo -n "." # The -n option to echo suppresses newline, 45 #+ so you get continuous rows of dots. 46 fi 47 48 sleep 1 49 done 50 51 52 # Note: if you change the KEYWORD variable to "Exit", 53 #+ this script can be used while on-line 54 #+ to check for an unexpected logoff. 55 56 # Exercise: Change the script, per the above note, 57 # and prettify it. 58 59 exit 0 60 61 62 # Nick Drage suggests an alternate method: 63 64 while true 65 do ifconfig ppp0 | grep UP 1> /dev/null && echo "connected" && exit 0 66 echo -n "." # Prints dots (.....) until connected. 67 sleep 2 68 done 69 70 # Problem: Hitting Control-C to terminate this process may be insufficient. 71 #+ (Dots may keep on echoing.) 72 # Exercise: Fix this. 73 74 75 76 # Stephane Chazelas has yet another alternative: 77 78 CHECK_INTERVAL=1 79 80 while ! tail -n 1 "$LOGFILE" | grep -q "$KEYWORD" 81 do echo -n . 82 sleep $CHECK_INTERVAL 83 done 84 echo "On-line" 85 86 # Exercise: Discuss the relative strengths and weaknesses 87 # of each of these various approaches.</PRE></TD></TR></TABLE><HR></DIV><DIVCLASS="NOTE"><TABLECLASS="NOTE"WIDTH="100%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="common/note.png"HSPACE="5"ALT="Note"></TD><TDALIGN="LEFT"VALIGN="TOP"><P>The <TTCLASS="OPTION">DEBUG</TT> argument to <BCLASS="COMMAND">trap</B> causes a specified action to execute after every command in a script. This permits tracing variables, for example. <DIVCLASS="EXAMPLE"><HR><ANAME="VARTRACE"></A><P><B>Example 29-7. Tracing a variable</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 3 trap 'echo "VARIABLE-TRACE> \$variable = \"$variable\""' DEBUG 4 # Echoes the value of $variable after every command. 5 6 variable=29 7 8 echo "Just initialized \"\$variable\" to $variable." 9 10 let "variable *= 3" 11 echo "Just multiplied \"\$variable\" by 3." 12 13 exit $? 14 15 # The "trap 'command1 . . . command2 . . .' DEBUG" construct is 16 #+ more appropriate in the context of a complex script, 17 #+ where placing multiple "echo $variable" statements might be 18 #+ clumsy and time-consuming. 19 20 # Thanks, Stephane Chazelas for the pointer. 21 22 23 Output of script: 24 25 VARIABLE-TRACE> $variable = "" 26 VARIABLE-TRACE> $variable = "29" 27 Just initialized "$variable" to 29. 28 VARIABLE-TRACE> $variable = "29" 29 VARIABLE-TRACE> $variable = "87" 30 Just multiplied "$variable" by 3. 31 VARIABLE-TRACE> $variable = "87"</PRE></TD></TR></TABLE><HR></DIV> </P></TD></TR></TABLE></DIV><P>Of course, the <BCLASS="COMMAND">trap</B> command has other uses aside from debugging.</P><DIVCLASS="EXAMPLE"><HR><ANAME="MULTIPLEPROC"></A><P><B>Example 29-8. Running multiple processes (on an SMP box)</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # parent.sh 3 # Running multiple processes on an SMP box. 4 # Author: Tedman Eng 5 6 # This is the first of two scripts, 7 #+ both of which must be present in the current working directory. 8 9 10 11 12 LIMIT=$1 # Total number of process to start 13 NUMPROC=4 # Number of concurrent threads (forks?) 14 PROCID=1 # Starting Process ID 15 echo "My PID is $$" 16 17 function start_thread() { 18 if [ $PROCID -le $LIMIT ] ; then 19 ./child.sh $PROCID& 20 let "PROCID++" 21 else 22 echo "Limit reached." 23 wait 24 exit 25 fi 26 } 27 28 while [ "$NUMPROC" -gt 0 ]; do 29 start_thread; 30 let "NUMPROC--" 31 done 32 33 34 while true 35 do 36 37 trap "start_thread" SIGRTMIN 38 39 done 40 41 exit 0 42 43 44 45 # ======== Second script follows ======== 46 47 48 #!/bin/bash 49 # child.sh 50 # Running multiple processes on an SMP box. 51 # This script is called by parent.sh. 52 # Author: Tedman Eng 53 54 temp=$RANDOM 55 index=$1 56 shift 57 let "temp %= 5" 58 let "temp += 4" 59 echo "Starting $index Time:$temp" "$@" 60 sleep ${temp} 61 echo "Ending $index" 62 kill -s SIGRTMIN $PPID 63 64 exit 0 65 66 67 # ======================= SCRIPT AUTHOR'S NOTES ======================= # 68 # It's not completely bug free. 69 # I ran it with limit = 500 and after the first few hundred iterations, 70 #+ one of the concurrent threads disappeared! 71 # Not sure if this is collisions from trap signals or something else. 72 # Once the trap is received, there's a brief moment while executing the 73 #+ trap handler but before the next trap is set. During this time, it may 74 #+ be possible to miss a trap signal, thus miss spawning a child process. 75 76 # No doubt someone may spot the bug and will be writing 77 #+ . . . in the future. 78 79 80 81 # ===================================================================== # 82 83 84 85 # ----------------------------------------------------------------------# 86 87 88 89 ################################################################# 90 # The following is the original script written by Vernia Damiano. 91 # Unfortunately, it doesn't work properly. 92 ################################################################# 93 94 #!/bin/bash 95 96 # Must call script with at least one integer parameter 97 #+ (number of concurrent processes). 98 # All other parameters are passed through to the processes started. 99 100 101 INDICE=8 # Total number of process to start 102 TEMPO=5 # Maximum sleep time per process 103 E_BADARGS=65 # No arg(s) passed to script. 104 105 if [ $# -eq 0 ] # Check for at least one argument passed to script. 106 then 107 echo "Usage: `basename $0` number_of_processes [passed params]" 108 exit $E_BADARGS 109 fi 110 111 NUMPROC=$1 # Number of concurrent process 112 shift 113 PARAMETRI=( "$@" ) # Parameters of each process 114 115 function avvia() { 116 local temp 117 local index 118 temp=$RANDOM 119 index=$1 120 shift 121 let "temp %= $TEMPO" 122 let "temp += 1" 123 echo "Starting $index Time:$temp" "$@" 124 sleep ${temp} 125 echo "Ending $index" 126 kill -s SIGRTMIN $$ 127 } 128 129 function parti() { 130 if [ $INDICE -gt 0 ] ; then 131 avvia $INDICE "${PARAMETRI[@]}" & 132 let "INDICE--" 133 else 134 trap : SIGRTMIN 135 fi 136 } 137 138 trap parti SIGRTMIN 139 140 while [ "$NUMPROC" -gt 0 ]; do 141 parti; 142 let "NUMPROC--" 143 done 144 145 wait 146 trap - SIGRTMIN 147 148 exit $? 149 150 : <<SCRIPT_AUTHOR_COMMENTS 151 I had the need to run a program, with specified options, on a number of 152 different files, using a SMP machine. So I thought [I'd] keep running 153 a specified number of processes and start a new one each time . . . one 154 of these terminates. 155 156 The "wait" instruction does not help, since it waits for a given process 157 or *all* process started in background. So I wrote [this] bash script 158 that can do the job, using the "trap" instruction. 159 --Vernia Damiano 160 SCRIPT_AUTHOR_COMMENTS</PRE></TD></TR></TABLE><HR></DIV><DIVCLASS="NOTE"><TABLECLASS="NOTE"WIDTH="100%"BORDER="0"><TR><TDWIDTH="25"ALIGN="CENTER"VALIGN="TOP"><IMGSRC="common/note.png"HSPACE="5"ALT="Note"></TD><TDALIGN="LEFT"VALIGN="TOP"><P><TTCLASS="USERINPUT"><B>trap '' SIGNAL</B></TT> (two adjacent apostrophes) disables SIGNAL for the remainder of the script. <TTCLASS="USERINPUT"><B>trap SIGNAL</B></TT> restores the functioning of SIGNAL once more. This is useful to protect a critical portion of a script from an undesirable interrupt.</P></TD></TR></TABLE></DIV><P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING"> 1 trap '' 2 # Signal 2 is Control-C, now disabled. 2 command 3 command 4 command 5 trap 2 # Reenables Control-C 6 </PRE></TD></TR></TABLE></P><TABLECLASS="SIDEBAR"BORDER="1"CELLPADDING="5"><TR><TD><DIVCLASS="SIDEBAR"><ANAME="AEN17884"></A><P><AHREF="bashver3.html#BASH3REF">Version 3</A> of Bash adds the following special variables for use by the debugger. <OLTYPE="1"><LI><P>$BASH_ARGC</P></LI><LI><P>$BASH_ARGV</P></LI><LI><P>$BASH_COMMAND</P></LI><LI><P>$BASH_EXECUTION_STRING</P></LI><LI><P>$BASH_LINENO</P></LI><LI><P>$BASH_SOURCE</P></LI><LI><P><AHREF="variables2.html#BASHSUBSHELLREF">$BASH_SUBSHELL</A></P></LI></OL></P></DIV></TD></TR></TABLE></DIV><H3CLASS="FOOTNOTES">Notes</H3><TABLEBORDER="0"CLASS="FOOTNOTES"WIDTH="100%"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="5%"><ANAME="FTN.AEN17836"HREF="debugging.html#AEN17836">[1]</A></TD><TDALIGN="LEFT"VALIGN="TOP"WIDTH="95%"><P>By convention, <TTCLASS="REPLACEABLE"><I>signal 0</I></TT> is assigned to <AHREF="exit-status.html#EXITCOMMANDREF">exit</A>. </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="zeros.html"ACCESSKEY="P">Prev</A></TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="index.html"ACCESSKEY="H">Home</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top"><AHREF="options.html"ACCESSKEY="N">Next</A></TD></TR><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top">Of Zeros and Nulls</TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="part5.html"ACCESSKEY="U">Up</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top">Options</TD></TR></TABLE></DIV></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -