避免Bash受挫-将Python用于Shell脚本

2020-11-09 04:51:51

我从来不习惯猛烈抨击脚本语法。每当我必须编写一个非常简单的bash脚本时,奇怪的语法就会让我恼火,而且我必须搜索我需要做的每一件小事,从如何在if语句中进行比较、如何使用sed等开始。

对我来说,使用Python作为Shell脚本语言似乎是更好的选择。我每天都在使用Python,并且非常了解它的语法。Python是一种更简洁、更具表现力的语言。它是简明扼要的。它有一个庞大的内置库,可以让你在不使用外壳命令的情况下执行许多任务,它是跨平台的,它可以预装或很容易安装在许多操作系统上。

在我的上一个项目中,在经历了一些bash挫折之后,我决定用CLI样式的Python脚本重构一组臃肿的bash脚本。这项工作的一个附带结果是一个很小的单一帮助程序文件,我将在这里与您分享这个文件,其中几乎没有什么实用程序可以弥补这一差距,使您可以轻松地使用Python编写Shell脚本。

为了让这个实用程序可以无处不在地运行,我让它同时兼容Python2.7和Python3.5+(从版本14开始,在Ubuntu中预装了Python2.7)。它完全没有第三方的要求,也不需要venv,我在Mac和Ubuntu上测试了它。

核心函数是sh(),它是subcess.Popen()的包装器。它允许您从Python执行Shell调用,并决定是否执行以下操作:

在Shell[subcess.Popen(Shell=true)]内运行该命令。考虑到外壳注入的可能性,这被认为是一种不安全的做法,但在外壳调用中允许许多方便的功能,如管道(|)、环境变量插值、使用&;&;一次调用执行多个语句等等,因此如果您的脚本没有得到用户输入,或者您信任您的输入,您可以选择使用它。

从stdin获得用户输入提示,兼容Python2.7和Python3+。

我在使用Python编写Shell脚本时发现的一个警告是,子进程不会在父Python进程死亡时终止。为此,我找到了一个嵌入在实用程序中的解决方案,即使用出口挂钩[at_exit()]杀死任何尚未终止的子进程。这种方法适用于像Ctrl-C这样的软终止,但不适用于更激进的终止,比如使用kill-9终止您的python脚本,并且可能会让子Shell命令继续运行。我对如何解决这一缺陷的新想法持开放态度。然而,由于大多数Shell脚本执行的都是短期命令,我不认为这是一种阻碍。