Chapter 19 Tips and Traps: Common Goofs for Novices

本文列举了在使用Shell脚本时常见的错误,如执行权限问题、文件找不到、路径问题、变量作用域、命令未找到、删除文件的安全隐患以及printf行为不预期等,并提供了相应的解决方案和调试方法,例如使用`set -x`进行脚本调试。
摘要由CSDN通过智能技术生成

1.1 Forgetting to Set Execute Permissions
 

First, you could invoke bash and give it the name of the script as a parameter:

Or second (and better still), you could set the execute permission on the script so that you can run it directly:

[maxwell@MaxwellDBA test]$ ./fun_calc.sh
-bash: ./fun_calc.sh: Permission denied
[maxwell@MaxwellDBA test]$ bash fun_calc.sh
[maxwell@MaxwellDBA test]$ chmod a+x fun_calc.sh
[maxwell@MaxwellDBA test]$ ./fun_calc.sh
[maxwell@MaxwellDBA test]$

1.2 Fixing "No such file or directory" Errors

[maxwell@MaxwellDBA Day0801]$ cat busted
#!/bin/bash -
echo "Hello World!"
[maxwell@MaxwellDBA Day0801]$ # This works
[maxwell@MaxwellDBA Day0801]$ ./busted
Hello World!
[maxwell@MaxwellDBA Day0801]$ # But if the file gets DOS line endings,we get:
[maxwell@MaxwellDBA Day0801]$ ./busted1
/bin/bash: will: No such file or directory
Hello World!
[maxwell@MaxwellDBA Day0801]$ 

1.3 Forgetting That the Current Directory Is Not in the $PATH

Either add the current directory to the $PATH variable, which we do not recommend, or reference the script via the current directory with a leading ./ before the script name, as in: $ ./busted

[maxwell@MaxwellDBA Day0801]$ busted
bash: busted: command not found
[maxwell@MaxwellDBA Day0801]$ ./busted
Hello World!
[maxwell@MaxwellDBA Day0801]$

1.4 Naming Your Script Test

[maxwell@MaxwellDBA Day0801]$ type test
test is a shell builtin
[maxwell@MaxwellDBA Day0801]$ 

1.5 Expecting to Change Exported Variables

[maxwell@MaxwellDBA Day0801]$ ./first.sh
VAL=5
in second
initially VAL=5
changed so VAL=12
back in first
VAL=5
[maxwell@MaxwellDBA Day0801]$ cat first.sh
#
# a simple example of a common mistake
#
# set the value:
export VAL=5
printf "VAL=%d\n" $VAL
#invoke our other script:
./second.sh
#
# now see what changed (hint:nothing!)
printf "%b" "back in first\n"
printf "VAL=%d\n" $VAL
[maxwell@MaxwellDBA Day0801]$ cat second.sh
#!/bin/bash
printf "%b" "in second\n"
printf "initially VAL=%d\n" $VAL
VAL=12
printf "changed so VAL=%d\n" $VAL
[maxwell@MaxwellDBA Day0801]$

 and the second script has to echo the final value (and only the final value) to STDOUT (it could redirect its other messages to STDERR):

[maxwell@MaxwellDBA Day0801]$ ./first.sh
VAL=5
in second
initially VAL=5
changed so VAL=12
back in first
VAL=5
[maxwell@MaxwellDBA Day0801]$ cat first.sh
#
# a simple example of a common mistake
#
# set the value:
export VAL=5
printf "VAL=%d\n" $VAL
#invoke our other script:
./second.sh
#
# now see what changed (hint:nothing!)
printf "%b" "back in first\n"
printf "VAL=%d\n" $VAL
[maxwell@MaxwellDBA Day0801]$ cat second.sh
#!/bin/bash
printf "%b" "in second\n"             >&2
printf "initially VAL=%d\n" $VAL      >&2
VAL=12
printf "changed so VAL=%d\n" $VAL     >&2
[maxwell@MaxwellDBA Day0801]$ 

1.6 Forgetting Quotes Leads to "command not found" on Assignments

You need quotes around the righthand side of the assignment to $ALLOPT. What is written above as: ALLOPT=$OPT1 $OPT2 really should be: ALLOPT="$OPT1 $OPT2"

[maxwell@MaxwellDBA Day0801]$ cat goof1.sh
#!/bin/bash -
# common goof:
# X=$Y $Z
# isn't the same as
# X="$Y $Z"
#
OPT1=-l
OPT2=-h
ALLOPT=$OPT1 $OPT2
ls $ALLOPT .
[maxwell@MaxwellDBA Day0801]$ chmod a+x goof1.sh
[maxwell@MaxwellDBA Day0801]$ ./goof1.sh
./goof1.sh: line 9: -h: command not found
busted  busted1  dash.sh  default_date.sh  first.sh  goof1.sh  load_mp3.sh  oodiff.sh  second.sh

[maxwell@MaxwellDBA Day0801]$ cat goof1.sh
#!/bin/bash -
# common goof:
# X=$Y $Z
# isn't the same as
# X="$Y $Z"
#
OPT1=-l
OPT2=-h
ALLOPT="$OPT1 $OPT2"
ls $ALLOPT .
[maxwell@MaxwellDBA Day0801]$ ./goof1.sh
total 36K
-rwxrwxr-x 1 maxwell maxwell   34 Aug  1 19:33 busted
-rwxrwxr-x 1 maxwell maxwell   58 Aug  1 19:39 busted1
-rw-rw-r-- 1 maxwell maxwell  595 Aug  1 13:27 dash.sh
-rw-rw-r-- 1 maxwell maxwell  915 Aug  1 08:11 default_date.sh
-rwxrwxr-x 1 maxwell maxwell  228 Aug  1 19:49 first.sh
-rwxrwxr-x 1 maxwell maxwell  123 Aug  1 19:59 goof1.sh
-rw-rw-r-- 1 maxwell maxwell 1.4K Aug  1 13:49 load_mp3.sh
-rw-rw-r-- 1 maxwell maxwell 1.3K Aug  1 13:58 oodiff.sh
-rwxrwxr-x 1 maxwell maxwell  145 Aug  1 19:54 second.sh
[maxwell@MaxwellDBA Day0801]$ 

1.10 Deleting Files Using an Empty Variable

Never do:
rm -rf $files_to_delete
Never, ever, ever do:
rm -rf /$files_to_delete
Use this instead:
[ "$files_to_delete" ] && rm -rf $files_to_delete

1.11 Seeing Odd Behavior from printf

[maxwell@MaxwellDBA Day0801]$ cat oddscript
#!/bin/bash -
badnode=6

printf "good nodes: %d\n" $goodnode
printf "bad nodes: %d\n" $badnode
printf "miss nodes: %d\n" $missnode
printf "GOOD=%d BAD=%d MISS=%d\n" $goodnode $badnode $missnode
[maxwell@MaxwellDBA Day0801]$ bash oddscript
good nodes: 0
bad nodes: 6
miss nodes: 0
GOOD=6 BAD=0 MISS=0
[maxwell@MaxwellDBA Day0801]$ 

1.13 Debugging Scripts

Add set -x to the top of the script when you run it. Or use set -x to turn on xtrace before a troublesome spot and set +x to turn it off after.

[maxwell@MaxwellDBA Day0801]$ cat buggy
#!/usr/bin/env bash
# cookbook filename: buggy
#
set -x 

result=$1

[ $result = 1 ] \
  && { echo "Result is 1; excellent." ; exit 0; } \
  || { echo "Uh-oh, ummm, RUN AWAY! " ; exit 120; }

Now we invoke this script, but first we set and export the value of the PS4 prompt. bash will print out the value of PS4 before each command that it displays during an execution trace (i.e., after a set -x ):

[maxwell@MaxwellDBA Day0801]$ cat buggy
#!/usr/bin/env bash
# cookbook filename: buggy
#
set -x 

result=$1

[ $result = 1 ] \
  && { echo "Result is 1; excellent." ; exit 0; } \
  || { echo "Uh-oh, ummm, RUN AWAY! " ; exit 120; }
[maxwell@MaxwellDBA Day0801]$ export PS4='+trace $LINENO:'
[maxwell@MaxwellDBA Day0801]$ echo $PS4
+trace $LINENO:
[maxwell@MaxwellDBA Day0801]$ chmod a+x buggy
[maxwell@MaxwellDBA Day0801]$ ./buggy
+trace 6:result=
+trace 8:'[' = 1 ']'
./buggy: line 8: [: =: unary operator expected
+trace 10:echo 'Uh-oh, ummm, RUN AWAY! '
Uh-oh, ummm, RUN AWAY! 
+trace 10:exit 120
[maxwell@MaxwellDBA Day0801]$ ./buggy 1
+trace 6:result=1
+trace 8:'[' 1 = 1 ']'
+trace 9:echo 'Result is 1; excellent.'
Result is 1; excellent.
+trace 9:exit 0
[maxwell@MaxwellDBA Day0801]$ ./buggy 2
+trace 6:result=2
+trace 8:'[' 2 = 1 ']'
+trace 10:echo 'Uh-oh, ummm, RUN AWAY! '
Uh-oh, ummm, RUN AWAY! 
+trace 10:exit 120
[maxwell@MaxwellDBA Day0801]$
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值