如果直接调用正在运行的脚本,而不是通过使用脚本路径作为参数调用其解释器,那么无论解释器如何,如何可靠地检索脚本文件的完整路径?
以下是一些方法不检索脚本的绝对路径:
readlink /proc/$PID/exe
返回的路径口译员如果 PID ${PID} 是一个脚本。cat /proc/$PID/comm
返回基本名称脚本的。- 看内容没有什么可靠的
/proc/$PID/cmdline
。这些内容可以由正在运行的程序更改,并且“第零”参数不能保证是脚本的实际路径(就像echo $0
在终端会话中运行时一样)。
答案1
操作系统对此无能为力,因为脚本只是解释器读取的一段数据。解释器可以使用脚本的主体,然后关闭文件,还可以以不跟踪脚本位置的方式操作全局参数向量。
由脚本语言提供对脚本名称和其他功能的访问,例如脚本能够拥有自己的命令行选项,这些选项不会被解释器视为自己的命令行选项。
如果脚本语言没有,您可能可以使用/proc
.如果您知道解释器在执行脚本文件时打开了脚本文件,并且它始终是某个文件描述符编号,那么您也许可以查看/proc/self/fd
.例如,这对我在特定的 GNU/Linux 系统上有效:
$ ./shellarg a b c
my name is /home/kaz/junk/shellarg
哪里shellarg
:
#!/bin/sh
mypath=$(readlink /proc/$$/fd/10)
echo "my name is $mypath"
我不推荐这样做,因为它取决于作为文件描述符 10 打开的脚本。更重要的是,对于这种特定的脚本语言,这是不必要的,因为 shell 表现良好并将脚本名称安装为$0
.
如果您使用某种敌对脚本语言,导致很难获取脚本名称,则可以通过 shell 包装器调用脚本,其中插入$0
:
#!/bin/sh
mydir=$(dirname "$0")
fbzfile="$mydir"/script.fbz
frobozz-interpreter -f $fbzfile -- $fbzfile ... other args
在这里,frobozz-interpreter
接收脚本名称作为其参数-f
,并对其保密。它会解析整个文件,然后在运行脚本之前关闭它,/proc
在脚本中扫描是徒劳的。然而,我们的 shell 包装器只是将脚本的名称作为第一个参数传递给该脚本。剧本预料到了这一点,一切都很好。