我试图编写一个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:错误无法恢复:现在退出
答案 0 :(得分:1)
有必要自己做吗?有一个名为makeself的现有工具可以为您执行此操作。如果您确实需要自己编写,请注意以下几点:
您的输出文件是一个存档,其前面有一个shell脚本。提取过程通过base64
和tar
运行整个输出文件,而不仅仅是存档。 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文件,其中包含命令行中命名的文件或目录,输出通过管道输出到GNU 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
并相应地进行调整。您需要在生成器脚本中进行一次测试,并在生成的脚本中进行测试的副本。这绝对是一个更精致的计划。