自解压tar档案(shell脚本)

时间:2016-03-10 17:03:13

标签: shell unix scripting tar self-extracting

我试图编写一个shell脚本,创建另一个自解压缩tar存档,该存档在base64中压缩和编码。我不知道在这里去哪里,对shell脚本没什么经验。

此脚本创建压缩和编码的tar存档,但当我尝试从终端运行./tarName时,自解压不起作用。任何建议表示赞赏

#!/bin/sh
tarName=$1;

if [ -e $tarName.tar.gz ] 

    then /bin/echo "$tarName already exists" 
    exit 0
fi

shift;
for files;
do
    tar -czvf tmpTarBall.tar.gz $files;
done

echo "#!/bin/sh" >> $tarName.tar.gz;
echo "base64 -d $tarName.tar.gz"  >> $tarName.tar.gz;
echo "tar -xzvf $tarName.tar.gz" >> $tarName.tar.gz;
chmod +x ./$tarName.tar.gz;

base64 tmpTarBall.tar.gz >> $tarName.tar.gz;
rm tmpTarBall.tar.gz;

---------- UPDATE

有些人环顾四周,这就是我现在所拥有的,仍然无效。任何人都可以向我解释原因吗?

#!/bin/sh
tarName=$1;

if [ -e $tarName.tar.gz ] 

    then /bin/echo "$tarName already exists" 
    exit 0
fi

shift;
for files;
do
    tar -czvf tmpTarBall.tar.gz $files;
done

cat > extract.sh;
echo "#!/bin/sh" >> extract.sh;
echo "sed '0,/^#TARBALL#$/d' $0 | $tarName.tar.gz | base64 -d | tar -xzv; exit 0" >> extract.sh;
echo "#TARBALL#" >> extract.sh;

cat extract.sh tmpTarBall.tar.gz > $tarName.tar.gz;
chmod +x ./$tarName.tar.gz;

rm extract.sh tmpTarBall.tar.gz;

当我尝试运行tarName.tar.gz时,我收到错误: ./tarName.tar.gz:2:./ tarName.tar.gz:tarName.tar.gz:找不到 gzip:stdin:意外的文件结束 tar:孩子返回状态1 tar:错误无法恢复:现在退出

2 个答案:

答案 0 :(得分:1)

有必要自己做吗?有一个名为makeself的现有工具可以为您执行此操作。如果您确实需要自己编写,请注意以下几点:

您的输出文件是一个存档,其前面有一个shell脚本。提取过程通过base64tar运行整个输出文件,而不仅仅是存档。 base64调用将脚本部分变为垃圾,然后混淆tar。您需要做的是添加一些代码,将脚本与存档分开,然后仅在存档部分运行其余命令。一种可行的方法是将提取脚本调整为以下内容:

#!/bin/sh
linenum=$(grep -n "__END_OF_SCRIPT_MARKER__" $tarName.tar.gz | tail -1 | sed -e 's/:.*//')
tail -n +$(($linenum + 1)) $tarName.tar.gz | base64 -d | tar -xzv
exit 0
__END_OF_SCRIPT_MARKER__

确保标记文本后面的脚本部分中没有 nothing ,除了换行符(此网站上的标记不可见)。这样,您就可以使用grep查找包含标记的行号,然后使用tail剥离多行。剩下的将是归档部分,它通常由其余代码处理。 exit行确保shell不会尝试将标记文本或存档内容作为代码执行。如果您愿意,可以将提取代码保留为压缩程度较低的格式,但您最终必须为归档部分创建临时文件并确保其被删除。

答案 1 :(得分:1)

期望的输出

概括地说,您要生成的脚本应如下所示:

base64 -d <<'EOF' | tar -xzf -
…base-64 encoded data…
EOF

base64命令解码其标准输入,该输入作为here文档提供,由仅包含EOF的行终止。输出写入 tar,提供从标准输入中提取gzip压缩数据的选项。

最小脚本

因此,最小的生成器脚本如下所示:

echo "base64 -d <<'EOF' | tar -czf -"
tar -czf - "$@" | base64 -w 72
echo "EOF"

这回显base64 … | tar …行,然后使用tar在标准输出上生成一个压缩的tar文件,其中包含命令行中命名的文件或目录,输出通过管道输出到GN​​U coreutils版本base64的{​​{1}}选项,指定输出行应为72个字符宽(加上换行符)。接下来是EOF以标记此处文档的结尾。

您可以将shebang行(#!/bin/sh)添加到其中一个或两个脚本中。没有必要选择更具体的外壳;这只使用了核心shell脚本构造,这些构造可以回溯到昔日的日子 - 在任何人的眼中,POSIX都是闪闪发光的。

可能的并发症

可能出现的并发症包括对Mac OS X base64的支持,其中包含如下用法消息:

Usage:  base64 [-dhvD] [-b num] [-i in_file] [-o out_file]
  -h, --help     display this message
  -D, --decode   decodes input
  -b, --break    break encoded string into num character lines
  -i, --input    input file (default: "-" for stdin)
  -o, --output   output file (default: "-" for stdout)

-v选项和-d选项都会生成base64: invalid option -- v(适用于相应的字母),以及使用情况。似乎不是一种从中获取版本信息的方法。但是,当您请求base64时,GNU的base64 --version会生成有用的消息。标准输出的第一行将包含以下内容:

base64 (GNU coreutils) 8.22
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Simon Josefsson.

这是写入标准输出。因此,您可以自动检测您是否具有GNU base64并相应地进行调整。您需要在生成器脚本中进行一次测试,并在生成的脚本中进行测试的副本。这绝对是一个更精致的计划。