第一种方法

第一种方法

我希望脚本能够复制自身,以便执行 cron 任务,但从脚本内部获取其位置却很难posix 中不可靠。更好的方法是将整个脚本制作成定界文档并获取它。

有没有一种优雅的 POSIX 方法来做到这一点?

到目前为止我已经尝试过,使用这个示例脚本:

#!/bin/sh
FOO='hello world'
echo "$FOO"
cat "$0"

第一种方法

它被写入/tmp/.script$$以便脚本可以在需要时将其复制到适当的位置(busybox 未使用 编译mktemp)。在 linux 2.6 上运行,无需/dev/fd//dev/stdin,但/proc/self/fd/可用。

#!/bin/sh
trap '{ rm -f "/tmp/.script$$"; exit; }' EXIT INT TERM
tee "/tmp/.script$$" <<'#SCRIPT' | . /proc/self/fd/0
#!/bin/sh
FOO='hello world'
echo "$FOO"
cat "/tmp/.script$$"
#SCRIPT

这是可行的,但它源自管道,这意味着外部没有可用的变量或函数。

第二种方法

#!/bin/sh
trap '{ rm -f "/tmp/.script$$"; exit; }' EXIT INT TERM
cat > "/tmp/.script$$" <<'#SCRIPT' && . "/tmp/.script$$"
#!/bin/sh
FOO='hello world'
echo "$FOO"
cat "/tmp/.script$$"
#SCRIPT

这里的范围是固定的,但执行取决于编写脚本的成功。

第三种方法

#!/bin/sh
trap '{ rm -f "/tmp/.script$$"; exit; }' EXIT INT TERM
. /proc/self/fd/0 <<EOF
$(tee "/tmp/.script$$" <<': "SCRIPT'
#!/bin/sh
FOO='hello world'
echo "$FOO"
cat "/tmp/.script$$"
: "SCRIPT
)
EOF
#"

从功能上来说,这就是我想要的,但它相当丑陋。

什么不起作用

#!/bin/sh
trap '{ rm -f "/tmp/.script$$"; exit; }' EXIT INT TERM
{ ( tee "/tmp/.script$$" >/proc/$$/fd/0 ) <<'#SCRIPT' & } && . /proc/self/fd/0
#!/bin/sh
FOO='hello world'
echo "$FOO"
cat "/tmp/.script$$"
#SCRIPT

这只是像交互式 shell 一样等待用户输入。我明白为什么它有效,因为标准输入没有关闭,但我不确定如何打开一个新的文件描述符而不将其链接到文件(如果我无论如何都要将它链接到文件,第二种方法是清洁工)。

相关内容