编写健壮的shell脚本的规则是什么



我最近用自己编写的shell脚本擦除了部分主目录。幸运的是,我确实以足够快的速度点击了Ctrl-C,避免了最坏的情况。

我的错误是过于依赖相对路径。从现在起,我在更改目录时总是使用绝对路径。。。但是,这让我想到了一个有趣的问题:编写健壮的shell脚本的规则是什么

我已经知道,当从一个目录移动到另一个目录时,应该始终使用绝对路径。但是,必须有很多其他的方法(例如,当命令失败时该怎么办,什么是停止脚本并通知用户的好方法)。

那么,有人有专门针对shell脚本的规则和提示列表吗?

几个想法:

  1. 在shebang中使用-e标志,例如#!/bin/sh -e。这样,脚本将在出现第一个错误时停止。这有点像在Java中抛出一个RuntimeException。这可能确实救了我几次,我有一种感觉,在这种情况下,它也会对你有所帮助。

  2. 处理脚本中所有语句的退出代码。实际上,在shebang中使用-e会迫使您这样做。

  3. 不要将命令与;连锁。请改用&&。同样,在shebang中使用-e将强制您执行此操作。

  4. 正确引用可能包含空格或其他特殊字符的路径。

  5. 如果一个脚本在没有参数的情况下使用时不会做危险的事情,那就最好了。

  6. 对于非琐碎的脚本,请确保使用-h--help标志来打印有用的消息。(我使用这个脚本来生成带有标志解析的脚本。)对于那些在没有参数的情况下调用时可能会做危险事情的脚本来说,这应该是强制性的。

  7. 在任何非正常退出时使用显式exit 1退出脚本。在没有任何参数的情况下处理if块中的错误,echo一些有用的消息,然后处理exit,这是一个常见的错误。由于exit使用上一个命令的退出代码,在本例中为echo,因此它将成功退出。请注意,在我前面链接的示例脚本中,当处理--help标志时,我在打印帮助消息后exit 1

  8. 如果您不需要bash功能,请使用#!/bin/sh shebang并尝试与旧版本保持兼容。我认为,可移植性是一种健壮性。

  9. 使用$()而不是``。更容易阅读~~更难犯错。

  10. 良好且一致地格式化代码。更易于阅读~~健壮性。

  11. 请注意平台之间的差异。例如,date --isodate +%F都以2013-11-17格式打印日期,但第一种仅适用于GNU系统,第二种也适用于BSD和Solaris。所以经常使用date +%F,它在任何地方都有效。这样的例子当然有一百个。如果你每天都在做一些你不习惯的事情,试着检查一下它是否在不同的系统中也能工作。

  12. 测试空变量,尤其是在像rm -fr这样的危险命令中。例如,如果TOPDIR或/和OBJDIR恰好为空或未设置,则rm -rf "$TOPDIR/$OBJDIR"的结果可能是灾难性的。一般来说,双重检查或三重检查类似危险命令的可能参数值。

  13. 不要突破shell脚本的限制。脚本应该是粘合代码。如果你发现自己在做一些棘手的事情,或者你需要晦涩的功能,那么你最好转向更强大的语言。

最后,这些都不能阻止你犯愚蠢的错误。

附言:我会继续回来,并添加更多我记得的东西。请随时提出改进建议,我会添加它们。谢谢

一般规则:你需要思考你正在做的事情。测试和调试是取得成功的一种方式。

无论你使用什么语言,都要分解问题。编写小程序。测试它们。必要时进行修复。用小的写出更复杂的。还有一个。

了解给定语言中的调试工具。在bash中,-x选项可以为您带来奇迹。此外,战略性地放置echo fooecho $variable可以帮你很多忙。

如果你需要做一些可能具有破坏性的事情(比如删除文件),请先进行试运行。将所有rm替换为echo,并检查结果。如果出现错误,您将在要删除的文件列表中看到。

测试数据准备的每一步。甚至,如果您在bash中编写了一个单行,请在添加管道和另一个阶段之前检查每个阶段的结果。及早发现问题并尽早解决。

请确保该解决方案是可扩展的。如果它对20个数据项有效,那么它对2万个数据项是否有效?

如果您的程序处理用户提供的数据,请确保它的行为正常,即使输入时出现垃圾。在这种情况下,报告错误并退出是一种明智的方式。

追求简洁。解决方案越简单,就越容易避免错误。

当然,我忘了在这里添加一些重要的内容:)

祝你编码成功!

最新更新