我有以下我无法理解的脚本。有人可以解释一下吗?
#!/bin/sh
skip=14
tmpdir=`/bin/mktemp -d ${TMPDIR:-/tmp}/gzexe.XXXXXXXXXX` || exit 1
prog="${tmpdir}/`echo \"$0\" | sed 's|^.*/||'`"
if /usr/bin/tail -n +$skip "$0" | "/bin"/gzip -cd > "$prog"; then
/bin/chmod 700 "$prog"
trap '/bin/rm -rf $tmpdir; exit $res' EXIT
"$prog" ${1+"$@"}; res=$?
else
echo "Cannot decompress $0"
/bin/rm -rf $tmpdir
exit 1
fi;
exit $res
答案1
就像 cas 和 kcmakwana 所说的那样,这个脚本是自解压的。
#!/bin/sh
这是一个 shebang 来表示这是一个 unix shell 脚本。
skip=14
$skip
我们声明一个带有字符串值的变量14
tmpdir=`/bin/mktemp -d ${TMPDIR:-/tmp}/gzexe.XXXXXXXXXX` || exit 1
这里的重音符号表示执行内容并将其放入新的命令字符串中。 (这与 ) 不同吗$(my command)
?在这里,我们尝试为临时目录声明一个名称。该${TMPDIR:-/tmp}
代码意味着我们获取环境变量的值$TMPDIR
(如果存在),否则我们使用/tmp
并将字符串附加/gzexe.XXXXXXXXXX
到我们正在生成的路径中。这|| exit 1
意味着如果该命令失败,我们将退出此脚本并显示 1 级错误(0 级表示成功)。看这个问题有关退出代码的更多信息。
prog="${tmpdir}/`echo \"$0\" | sed 's|^.*/||'`"
这里我们为文件路径定义另一个变量。正在$0
扩展该脚本的名称。sed
我们将该字符串通过管道传输到的命令是修剪该路径的前导部分./
。这里将 sed 视为您通过管道输入的字符串的搜索和替换函数。因此,如果我们将此脚本命名为myscript.sh
,$0
并且./myscript.sh
应该$prog
包含/tmp/myscript.sh
.这是最好的行为吗?
if /usr/bin/tail -n +$skip "$0" | "/bin"/gzip -cd > "$prog"; then
在这里,我们从该脚本的第 14 行开始输出内容,$0
并将该内容通过标志传输到 gzip 中,-c and -d
该标志依次解压缩传入的文本并将结果打印到标准输出。接下来,标准输出被重定向到$prog
我们之前声明的文件路径。这是最好的行为吗?明确地将预期内容回显到 中会更安全吗$prog
?
/bin/chmod 700 "$prog"
在这里,我们为生成的文件设置权限,以便所有者可以读/写/执行,但其他人无法对该文件执行任何操作。
trap '/bin/rm -rf $tmpdir; exit $res' EXIT
使用 trap 命令的典型场景是捕获 SIGINT 信号。当用户通过按 Ctrl+C 中断脚本的执行时,系统会发送此信号。因此,当用户发送 ctrl-c 命令时,脚本将尝试删除位于的文件并以我们在下一行中声明的$tmpdir
级别退出$res
"$prog" ${1+"$@"}; res=$?
exit $res
在这里,我们执行脚本 at$prog
并向其传递参数,${1+"$@"}
这基本上意味着我们扩展传递到该脚本中的任何参数,即"$1" "$2" "$3" ...
。查看该语法的解释这里。最后,我们保存该命令的退出状态结果并将其保存到$res
($?
是最近的前台管道退出状态)。最后我们以相同的退出级别退出。
else
echo "Cannot decompress $0"
/bin/rm -rf $tmpdir
exit 1
fi;
非常简单,如果if
上面的命令不起作用,我们删除临时脚本副本$tmpdir
并以状态 1(错误)退出。