2011-10-05 113 views
4

我有一堆脚本,我正在调试,所有嵌套和相当讨厌。相当于-x的Bash环境变量?

只是想知道如果我能够设置一些相当于-x选项到bash的环境变量。这将节省我惊人的时间。

我已经寻找答案,但似乎它不存在 - 希望你聪明的人可能能够提供建议,或者可能的替代解决方案。

谢谢!

回答

8

因为你好像处于困境中,所以我会提出一些可怕的选择(还有一个选项听起来很糟糕,但并不那么糟糕)。

首选:使用不同的工具。 strace(1)ltrace(1)都可以提供一系列惊人的信息 - 虽然没有人了解有关shell变量的任何信息,但他们会告诉您脚本如何与系统的其他部分以及程序的某些内部状态进行交互。这可能是够好的。 (如果你是新来strace(1),尝试strace -f -o /tmp/foo ./program - 它会跟随fork(2)vfork(2)clone(2)调用,因此子进程遵循和倾倒太输出为/tmp/foo。)

第二选择:全部更换#!/bin/bash在所有的脚本#!/bin/bash -x

find . -type f -print0 | xargs -0 sed -i -e 's/^#!\/bin\/bash$/#!\/bin\/bash -x/' 

也许有替换的所有脚本shebang行一个更好的机制,但这种感觉好吗。它会在通过脚本调用的C程序中错过system(3)popen(3)等的所有用途,但这可能会很好。如果任何脚本依赖于参数/bin/bash,则可能需要更加努力才能正确添加-x

最后一个选择:以root身份启动sash(1) shell。复制/bin/bash/bin/real.bash。编写一个快速肮脏的C程序,将-x添加到/bin/real.bash的命令行参数中,将它放入/bin/bash。这将得到的一切:每system(3),每popen(3),每个初始化脚本,所有cron作业,所有用户登录,一切。

您可以稍微修改最后一个选择; Linux内核提供了每个进程的私有名称空间,可用于使新的/bin/bash仅对给定进程的儿童可见。这是一个有点复杂......

  1. 使bash副本:cp /bin/bash /bin/real.bash
  2. 写您的C包装加-x到命令行参数,并调用/bin/real.bash。 (让我们叫它/bin/wrapper.bash。)
  3. 充分利用/安装sharedmount --make-shared /
  4. 创建一个新的文件系统命名空间:unshare --mount bash
  5. bash,使/奴隶:mount --make-slave /
  6. bash,绑定贴装您的替换bashmount -B /bin/wrapper.bash /bin/bash
  7. ne wbash,启动你的shell脚本。他们都将被重定向到你的包装。不从bash不下降的过程将继续使用未修改的“真实”/bin/bash

当最后一个(grand)*子进程死亡时,私有名称空间和有趣的绑定挂载也消失了。

所有这些有趣的业务的结果是,所有的shell脚本保持不变,你可以使用你认为最有用的调试工具。如果你恰好眯起你的眼睛,这不是非常侵扰性的。

我新的命名空间内部和外部的新执行的很多步骤我的工作站上(除了我以前--make-rshared--make-rslave代替,并与/bin/dir/bin/ls,而不是/bin/bash测试),并检查了inode编号与ls -li /bin/dir /bin/ls从壳名称空间以及名称空间外的进程继续看到inode编号保持不变,但名称空间内的进程看到共享inode编号为dirls

对于命名空间的全部细节,私人坐骑,和绑定安装,我建议你阅读从内核源代码树的Documentation/filesystems/sharedsubtree.txt文件时,clone(2)帮助页面,unshare(1)手册页和mount(8)手册页。

绑定挂载在系统重新启动时就会消失,所以你不能拧得太紧。 :)

+0

谢谢;我已经在我的待办事项清单上“真正了解了私有名称空间和共享子树”,这看起来像是一个完美的应用程序。 – sarnold

+0

大概说'mv/bin/bash /bin/bash.real; printf'#!/ bin/bash.real \ n/bin/bash.real -x“$ @”\ n'>/bin/bash; chmod a + x/bin/bash'而不用C来打扰。 – Sorpigal

+0

@Sorpigal只适用于相当新的Linux内核 - 旧版内核无法正常工作,shebang指向具有shebang的脚本。 –

2

不,它不受环境变量控制,但您可以在需要的地方执行set -x,然后在set +x的地方将其关闭。