• Chapter 19 Tips and Traps: Common Goofs for Novices


    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:

    1. [maxwell@MaxwellDBA test]$ ./fun_calc.sh
    2. -bash: ./fun_calc.sh: Permission denied
    3. [maxwell@MaxwellDBA test]$ bash fun_calc.sh
    4. [maxwell@MaxwellDBA test]$ chmod a+x fun_calc.sh
    5. [maxwell@MaxwellDBA test]$ ./fun_calc.sh
    6. [maxwell@MaxwellDBA test]$

    1.2 Fixing "No such file or directory" Errors

    1. [maxwell@MaxwellDBA Day0801]$ cat busted
    2. #!/bin/bash -
    3. echo "Hello World!"
    4. [maxwell@MaxwellDBA Day0801]$ # This works
    5. [maxwell@MaxwellDBA Day0801]$ ./busted
    6. Hello World!
    7. [maxwell@MaxwellDBA Day0801]$ # But if the file gets DOS line endings,we get:
    8. [maxwell@MaxwellDBA Day0801]$ ./busted1
    9. /bin/bash: will: No such file or directory
    10. Hello World!
    11. [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

    1. [maxwell@MaxwellDBA Day0801]$ busted
    2. bash: busted: command not found
    3. [maxwell@MaxwellDBA Day0801]$ ./busted
    4. Hello World!
    5. [maxwell@MaxwellDBA Day0801]$

    1.4 Naming Your Script Test

    1. [maxwell@MaxwellDBA Day0801]$ type test
    2. test is a shell builtin
    3. [maxwell@MaxwellDBA Day0801]$

    1.5 Expecting to Change Exported Variables

    1. [maxwell@MaxwellDBA Day0801]$ ./first.sh
    2. VAL=5
    3. in second
    4. initially VAL=5
    5. changed so VAL=12
    6. back in first
    7. VAL=5
    8. [maxwell@MaxwellDBA Day0801]$ cat first.sh
    9. #
    10. # a simple example of a common mistake
    11. #
    12. # set the value:
    13. export VAL=5
    14. printf "VAL=%d\n" $VAL
    15. #invoke our other script:
    16. ./second.sh
    17. #
    18. # now see what changed (hint:nothing!)
    19. printf "%b" "back in first\n"
    20. printf "VAL=%d\n" $VAL
    21. [maxwell@MaxwellDBA Day0801]$ cat second.sh
    22. #!/bin/bash
    23. printf "%b" "in second\n"
    24. printf "initially VAL=%d\n" $VAL
    25. VAL=12
    26. printf "changed so VAL=%d\n" $VAL
    27. [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):

    1. [maxwell@MaxwellDBA Day0801]$ ./first.sh
    2. VAL=5
    3. in second
    4. initially VAL=5
    5. changed so VAL=12
    6. back in first
    7. VAL=5
    8. [maxwell@MaxwellDBA Day0801]$ cat first.sh
    9. #
    10. # a simple example of a common mistake
    11. #
    12. # set the value:
    13. export VAL=5
    14. printf "VAL=%d\n" $VAL
    15. #invoke our other script:
    16. ./second.sh
    17. #
    18. # now see what changed (hint:nothing!)
    19. printf "%b" "back in first\n"
    20. printf "VAL=%d\n" $VAL
    21. [maxwell@MaxwellDBA Day0801]$ cat second.sh
    22. #!/bin/bash
    23. printf "%b" "in second\n" >&2
    24. printf "initially VAL=%d\n" $VAL >&2
    25. VAL=12
    26. printf "changed so VAL=%d\n" $VAL >&2
    27. [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"

    1. [maxwell@MaxwellDBA Day0801]$ cat goof1.sh
    2. #!/bin/bash -
    3. # common goof:
    4. # X=$Y $Z
    5. # isn't the same as
    6. # X="$Y $Z"
    7. #
    8. OPT1=-l
    9. OPT2=-h
    10. ALLOPT=$OPT1 $OPT2
    11. ls $ALLOPT .
    12. [maxwell@MaxwellDBA Day0801]$ chmod a+x goof1.sh
    13. [maxwell@MaxwellDBA Day0801]$ ./goof1.sh
    14. ./goof1.sh: line 9: -h: command not found
    15. busted busted1 dash.sh default_date.sh first.sh goof1.sh load_mp3.sh oodiff.sh second.sh
    16. [maxwell@MaxwellDBA Day0801]$ cat goof1.sh
    17. #!/bin/bash -
    18. # common goof:
    19. # X=$Y $Z
    20. # isn't the same as
    21. # X="$Y $Z"
    22. #
    23. OPT1=-l
    24. OPT2=-h
    25. ALLOPT="$OPT1 $OPT2"
    26. ls $ALLOPT .
    27. [maxwell@MaxwellDBA Day0801]$ ./goof1.sh
    28. total 36K
    29. -rwxrwxr-x 1 maxwell maxwell 34 Aug 1 19:33 busted
    30. -rwxrwxr-x 1 maxwell maxwell 58 Aug 1 19:39 busted1
    31. -rw-rw-r-- 1 maxwell maxwell 595 Aug 1 13:27 dash.sh
    32. -rw-rw-r-- 1 maxwell maxwell 915 Aug 1 08:11 default_date.sh
    33. -rwxrwxr-x 1 maxwell maxwell 228 Aug 1 19:49 first.sh
    34. -rwxrwxr-x 1 maxwell maxwell 123 Aug 1 19:59 goof1.sh
    35. -rw-rw-r-- 1 maxwell maxwell 1.4K Aug 1 13:49 load_mp3.sh
    36. -rw-rw-r-- 1 maxwell maxwell 1.3K Aug 1 13:58 oodiff.sh
    37. -rwxrwxr-x 1 maxwell maxwell 145 Aug 1 19:54 second.sh
    38. [maxwell@MaxwellDBA Day0801]$

    1.10 Deleting Files Using an Empty Variable

    1. Never do:
    2. rm -rf $files_to_delete
    3. Never, ever, ever do:
    4. rm -rf /$files_to_delete
    5. Use this instead:
    6. [ "$files_to_delete" ] && rm -rf $files_to_delete

    1.11 Seeing Odd Behavior from printf

    1. [maxwell@MaxwellDBA Day0801]$ cat oddscript
    2. #!/bin/bash -
    3. badnode=6
    4. printf "good nodes: %d\n" $goodnode
    5. printf "bad nodes: %d\n" $badnode
    6. printf "miss nodes: %d\n" $missnode
    7. printf "GOOD=%d BAD=%d MISS=%d\n" $goodnode $badnode $missnode
    8. [maxwell@MaxwellDBA Day0801]$ bash oddscript
    9. good nodes: 0
    10. bad nodes: 6
    11. miss nodes: 0
    12. GOOD=6 BAD=0 MISS=0
    13. [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.

    1. [maxwell@MaxwellDBA Day0801]$ cat buggy
    2. #!/usr/bin/env bash
    3. # cookbook filename: buggy
    4. #
    5. set -x
    6. result=$1
    7. [ $result = 1 ] \
    8. && { echo "Result is 1; excellent." ; exit 0; } \
    9. || { 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 ):

    1. [maxwell@MaxwellDBA Day0801]$ cat buggy
    2. #!/usr/bin/env bash
    3. # cookbook filename: buggy
    4. #
    5. set -x
    6. result=$1
    7. [ $result = 1 ] \
    8. && { echo "Result is 1; excellent." ; exit 0; } \
    9. || { echo "Uh-oh, ummm, RUN AWAY! " ; exit 120; }
    10. [maxwell@MaxwellDBA Day0801]$ export PS4='+trace $LINENO:'
    11. [maxwell@MaxwellDBA Day0801]$ echo $PS4
    12. +trace $LINENO:
    13. [maxwell@MaxwellDBA Day0801]$ chmod a+x buggy
    14. [maxwell@MaxwellDBA Day0801]$ ./buggy
    15. +trace 6:result=
    16. +trace 8:'[' = 1 ']'
    17. ./buggy: line 8: [: =: unary operator expected
    18. +trace 10:echo 'Uh-oh, ummm, RUN AWAY! '
    19. Uh-oh, ummm, RUN AWAY!
    20. +trace 10:exit 120
    21. [maxwell@MaxwellDBA Day0801]$ ./buggy 1
    22. +trace 6:result=1
    23. +trace 8:'[' 1 = 1 ']'
    24. +trace 9:echo 'Result is 1; excellent.'
    25. Result is 1; excellent.
    26. +trace 9:exit 0
    27. [maxwell@MaxwellDBA Day0801]$ ./buggy 2
    28. +trace 6:result=2
    29. +trace 8:'[' 2 = 1 ']'
    30. +trace 10:echo 'Uh-oh, ummm, RUN AWAY! '
    31. Uh-oh, ummm, RUN AWAY!
    32. +trace 10:exit 120
    33. [maxwell@MaxwellDBA Day0801]$
  • 相关阅读:
    pytest-gitignore插件详解
    pyltp postagger 运行过程中报错Process finished with exit code -1073740791 (0xC0000409)
    MapInfo格式到ArcGIS格式的转换方法
    从零开始学数据结构系列之第一章《双链表》
    蓝桥杯每日一题2023.11.18
    Redis 哨兵集群方案
    pink老师 JavaScript基础以及进阶笔记
    springMVC参数绑定源码分析
    关于我的项目-微信小程序2(uniapp->wx小程序)
    大数据管理平台有什么用?如何利用大数据管理平台优化企业运营?
  • 原文地址:https://blog.csdn.net/u011868279/article/details/126108239