将tar.gz打包成shell脚本

9

我想知道如何将tar.gz文件打包到一个shell脚本中,就像idk**.bin一样。这样我就可以用一个shell文件交付程序,而不是tar.gz文件。


1
基本概念是编写一个 shell 脚本,它知道如何从文件末尾截取 tarball,然后只需将脚本和归档文件合并即可。 - Etan Reisner
1
在某些情况下,对tarball进行base64编码然后再添加它可能是一个好主意,这样负载中的非可打印字符就不会在脚本显示时引起问题。 - Michael Jaros
我第一次看到一个有着巨大负载的.sh文件时感到非常惊讶。因此,我认为这是一个有价值的问题,因为我想象其他人也会同样惊讶。 - Wyck
2个回答

15

有一篇Linux Journal文章详细解释了如何完成此操作,其中包括打包有效载荷的代码等。正如Etan Reisner在他的评论中所说,提取/安装脚本知道如何切掉其尾部以获取之前连接的有效载荷。以下是演示其工作原理的示例:

#!/bin/bash
# a self-extracting script header

# this can be any preferred output directory
mkdir ./output_dir

# determine the line number of this script where the payload begins
PAYLOAD_LINE=`awk '/^__PAYLOAD_BELOW__/ {print NR + 1; exit 0; }' $0`

# use the tail command and the line number we just determined to skip
# past this leading script code and pipe the payload to tar
tail -n+$PAYLOAD_LINE $0 | tar xzv -C ./output_dir

# now we are free to run code in output_dir or do whatever we want

exit 0

# the 'exit 0' immediately above prevents this line from being executed
__PAYLOAD_BELOW__

请注意使用$0来表示脚本本身。

要首先创建安装程序,您需要将上述代码和要安装/交付的tarball连接起来。如果上面的脚本称为extract.sh,并且负载称为payload.tar.gz,则此命令可以解决问题:

cat extract.sh payload.tar.gz > run_me.sh

不完全是这样,Jahid。你需要修改以tail开头的行中管道运算符后面的命令,来调用能处理你选择的归档文件的程序。如果该程序不能处理标准输入,则需要将归档文件写入文件中,然后在该文件上调用归档处理程序。 - Randall Cook

4
你也可以这样做:
#!/bin/bash
BASEDIR=`dirname "${0}"`
cd "$BASEDIR"

payload=$1
script=$2
tmp=__extract__$RANDOM

[ "$payload" != "" ] || read -e -p "Enter the path of the tar archive: " payload
[ "$script" != "" ] || read -e -p "Enter the name/path of the script: " script

printf "#!/bin/bash
PAYLOAD_LINE=\`awk '/^__PAYLOAD_BELOW__/ {print NR + 1; exit 0; }' \$0\`
tail -n+\$PAYLOAD_LINE \$0 | tar -xvz
#you can add custom installation command here

exit 0
__PAYLOAD_BELOW__\n" > "$tmp"

cat "$tmp" "$payload" > "$script" && rm "$tmp"
chmod +x "$script"

如果您将此文件保存为t2s,那么您可以像这样使用它:
t2s test.tar.gz install.sh

运行 install.sh 将会在当前目录中提取内容。如果需要,您也可以运行自定义安装脚本。您需要将它们适当地添加到 printf 部分。

如果您需要对其他压缩类型(例如 .tar.bz2)执行此操作,则需要编辑该部分中的 z 选项:

tail -n+\$PAYLOAD_LINE \$0 | tar xzv
#it's inside a quote and $ needs to be printed, so you will need to use \

例如:
对于 .tar.bz2 文件:
tail -n+\$PAYLOAD_LINE \$0 | tar xjv 
#it's inside a quote and $ needs to be printed, so you will need to use \

对于 .tar

tail -n+\$PAYLOAD_LINE \$0 | tar xv 
#it's inside a quote and $ needs to be printed, so you will need to use \

关于此选项的信息,您可以查看tar的man页面:

man tar

我已经将其制成一个工具来自动化这些任务。

好的方式,Jahid,所有都在一个文件中。+1。但我认为你不需要这一行pay=\cat $payload`。首先,$pay从未被使用,其次,如果$payload`是一个多GB的文件,那么将其加载到变量中可能会出现问题。;) - Randall Cook

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接