通常,一周前您会来到计算机上并找到某种在系统用户下运行的脚本。 是谁推出的? 在哪里可以找到这个run.php? 或者,您将一项添加到/ etc / crontab中,并且脚本在那里崩溃,并显示“找不到命令”错误。 怎么了 怎么办?
我有这些问题的答案。

环境变量
在几乎所有现代操作系统中,进程都有环境变量。 从技术上讲,它们是命名字符串的集合。 如果启动了子进程,那么它将自动继承父级环境的副本。
其中包括PATH变量(指示搜索可执行文件的路径),HOME变量(指示用户的主目录),负责用户的语言首选项的变量,以及许多其他变量。
有很多评论描述了这些变量的含义,但是实际上没有关于如何研究问题的文章。 填补这一空白。
谁开始这个过程?
因此,我们发现一个星期前在系统用户下运行的脚本。 是谁推出的? 怎么了 也许他们只是忘了他? 可能有10到15个人可以启动它,您不会采访所有人。 如何找到它是谁? 而这个run.php在哪里呢?
$ ps x | grep run.php 10684 ? Ss 472:25 /local/php/bin/php run.php
进程环境变量和sudo功能可以解决。 有一个PWD变量,shell在其中存储当前的工作目录。 实际上,此值将在运行命令时保存有关当前目录的信息。 另外,默认情况下,sudo实用程序会将信息留在进程环境变量中,有关它是从哪个用户启动的。
在/ proc中可以找到任何正在运行的进程的环境变量(还有更多)。 瞧:
$ cat /proc/10684/environ | tr '\0' '\n' | grep SUDO_USER SUDO_USER=alexxz $ cat /proc/10684/environ | tr '\0' '\n' | grep PWD PWD=/home/etlmaster
天哪,我自己启动了它。 好吧,谁不会发生?
通常,在简单情况下使用这种简单方法,您可以找到有关该过程的信息,而这些信息通常不可用。
该脚本可从命令行运行,但不适用于cron
您必须考虑环境变量的一种情况是,添加到/ etc / crontab的脚本因错误而崩溃。 您通过SSH进入服务器,运行命令,一切似乎都能正常进行。 当它自动启动时,它显示类似“蜂巢:找不到命令”的内容。
通常,将可执行命令的完整路径编写为好习惯,但这并不总是可能的。 在这种情况下,开发人员会尽力而为。 有人在crontab中将所需的路径添加到PATH中,作为团队的一部分。 更有经验的人将其命令包装在bash -l中。 而且,经历过艰辛的乌鸦炸弹仍然不会忘记聚集。 一切都是这样:制作,添加到监视中并忘记了。
经过这样的操作,沉积物仍然存在于真正工程师的灵魂中。 是的,问题已解决。 但是我不明白发生了什么! 一种方法比另一种方法更好? 所有这些设置都存储在哪里,并更改了谁?
让我们比较一下从皇冠启动时该进程所具有的环境变量和我们在命令行上所具有的环境变量。 我们记录来自王冠和当前环境的env命令的输出:
$ echo "* * * * * env > ~/crontab.env" | crontab; sleep 60; echo "" | crontab; $ env > my.env
查看PATH变量中的内容:
> grep ^PATH= crontab.env my.env Crontab.env: PATH=/usr/bin:/bin My.env: PATH=/local/hive/bin:/local/python/bin:/local/hadoop/bin:/local/hadoop/bin:/local/hive/bin:/local/hadoop/bin:/usr/local/bin:/usr/bin:/bin

妈妈咪呀! 因此,皇冠之下只有极少的东西! 当然,您需要加载正常的环境变量。
让我们看看如果添加bash -l将会是什么样的环境:
$ echo "* * * * * bash -l env > ~/crontab.env" | crontab; sleep 60; echo "" | crontab; alexxz@bi1.mlan:~> grep ^PATH= crontab.env my.env Crontab.env: PATH=/local/hive/bin:/local/python/bin:/local/hadoop/bin:/local/hadoop/bin:/local/hadoop/bin:/local/hive/bin:/usr/local/bin:/usr/bin:/bin My.env: PATH=/local/hive/bin:/local/python/bin:/local/hadoop/bin:/local/hadoop/bin:/local/hive/bin:/local/hadoop/bin:/usr/local/bin:/usr/bin:/bin
区别不是那么明显。 显示所有路径。 有些顺序不同,有些重复,但这已经比以前好多了。 其余变量也进行了很好的调整。 当然,来自SSH的变量的区域设置略有不同,但这不应再严重影响脚本的操作。
现在很清楚,为什么在crontab条目中需要bash -l。 并且,当然,不要忘记羊群。
调试登录脚本的初始化
这个问题似乎已经解决,皇冠上的所有产品都可以正常工作。 但是,如何在PATH变量中重复某些路径呢? 因此,服务器设置中有些混乱。 让我们尝试找出答案。
我们开放了一些人来初始化环境,我们读出了执行哪些脚本和执行的顺序,并满腔热情地开始流连忘返-几分钟后便感到绝望。 有关ls命令的某些特殊情况的体系结构,终端和极其重要的颜色设置的无穷无尽的条件流。 痛苦,绝望,恨! 我们对一个该死的变量PATH感兴趣!
实际上,一切都比较简单。 见面:
env -i bash -x -l -c 'echo 123' > login.log 2>&1
这个团队做什么? 使用原始环境创建一个新的bash进程,指示必须运行初始化脚本并在login.log文件中详细保护所有内容。 现在,我们有机会不在脑海中执行所有脚本,而只是阅读执行该脚本的内容,位置和时间,以及该环境设置的来源。
我不会详细分析如何读取结果日志。 那里的一切几乎都是微不足道的。 我只提到一个命中来自/ etc / profile,两个命中来自/etc/bash.bashrc。 是的,当在pappet中设置软件包时,它们太聪明了。 好吧,什么都没有,它不会打扰我工作。
但是现在我知道了,可以!
PS在非常困难的情况下,为了完全理解所有内容,可以将命令包装在strace中:
strace -f env -i bash -x -l -c 'echo 123' > login.log 2>&1