【问题标题】:self extracting tar archive (shell scripting)自解压 tar 存档(shell 脚本)
【发布时间】:2016-06-25 16:03:16
【问题描述】:

我试图编写一个 shell 脚本来创建另一个以 base64 压缩和编码的自解压 tar 存档。我不知道从哪里开始,并且几乎没有 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;

---------更新

环顾四周,这就是我现在所拥有的,但仍然无法正常工作。谁能给我解释一下为什么?

#!/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:标准输入:文件意外结束 焦油:孩子返回状态1 tar:错误不可恢复:现在退出

【问题讨论】:

  • exit 1 出现问题时 — exit 0 表示成功。您应该只用tar -czvf tmpTarBall.tar.gz "$@" 替换for 循环,以将所有文件放入一个tarball。 c 选项每次都会创建一个 tar 文件;因此,您只存储了列出的最后一个文件。
  • 你需要仔细考虑生成的 shell 脚本应该是什么样子,因为这将决定你的 shell 脚本必须做什么来创建它。您当前提出的命令行在许多方面都令人怀疑,尤其是因为您无法在正常的事件过程中通过 gzip 压缩的 tar 文件传输数据。总的来说,您可能应该使用-b num 选项在base64 的编码输出上设置行长(这在Mac OS X 上是正确的;GNU 版本有可能使用不同的选项)。

标签: shell unix scripting tar self-extracting


【解决方案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__

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

【讨论】:

  • 当我尝试将其回显到我的文件中时,并没有包含所有内容。我得到:#!/bin/sh linenum= tail -n +1 newTarTest.tar.gz | base64 -d | tar -xzv exit 0 __END_OF_SCRIPT_MARKER__
  • @minusila - 当使用 echo 将脚本写入输出文件时,您需要转义特殊字符,例如“$()”。否则,shell 将在 echo 发生之前评估它们。
【解决方案2】:

期望的输出

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

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

base64 命令对其标准输入进行解码,该标准输入作为 here 文档提供,以仅包含 EOF 的行结尾。输出写入 tar 带有从标准输入中提取 gzipped 数据的选项。

极简脚本

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

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

这会回显base64 … | tar … 行,然后使用tar 在标准输出上生成一个压缩的tar 文件,其中包含命令行中指定的文件或目录,并且输出通过管道传送到base64 的GNU coreutils 版本可以选择指定输出行应为 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 --version 时,GNU 的base64 确实会生成一条有用的消息。标准输出的第一行将包含如下内容:

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 并进行相应调整。您需要生成器脚本中的一个测试,以及生成脚本中的测试副本。这绝对是一个更精致的程序。

【讨论】:

    猜你喜欢
    • 2016-10-08
    • 1970-01-01
    • 2015-08-23
    • 1970-01-01
    • 2019-07-26
    • 2019-04-18
    • 1970-01-01
    • 2020-12-25
    • 1970-01-01
    相关资源
    最近更新 更多