
有时,您需要一种快速可靠的方式向用户分发数据或软件,无需使用包管理器(比如说,最终用户可能没有安装应用程序的root访问权限)。
这个问题可以通过使用容器和Podman或Docker来解决,但如果它们在目标系统上没有,怎么办?如果要求之一是应用程序在裸机环境中正常工作,又怎么办?
您可以将Python与pip一起使用(您可能知道也可以打包非Python工件),但是那样可能面临一些安装上的限制(虚拟环境或--user选项),更不用说需要样板代码来打包Python代码了。
我在本文中演示了一种非常小巧但有效的技术来编写不需要提升权限的自解压脚本。
设置您的数据
Damiaan Zwietering有一个很酷的关于新冠病毒的Git代码存储库,带有数据和可视化(Jupyter书籍和Excel电子表格),但没有安装程序。假设您想将其提供给自己的用户,但他们无权访问Git。您就可以为用户创建自解压安装程序。
在实际情况下,您已经拥有想要分发的数据。但是您有一些示例数据要处理,首先将该存储库克隆到主目录:
- $ git clone https://gitlab.com/dzwietering/corona.git
现在有很多数据和不那么浅的目录结构,但是您可以使用git archive命令创建一个.tar文件:
- $ cd $HOME / corona
- $ git archive --verbose --output $tempdir/corona.tar.gz HEAD
对于本示例,该打包文件是您想要与用户共享的文件。
自解压脚本的结构
自解压脚本分为以下几个部分:
1. 帮助用户提取数据的代码(“有效载荷”)
2. 从脚本中分离数据(要提取)的锚点
3. 提取其后数据的锚点位置
事实证明,Bash非常擅长以这种方式来定义脚本。
创建有效载荷
这里有个想法:假设您需要分发的数据是一个含有许多脚本和数据的目录。您希望保持权限和结构完好无缺,您希望用户将其“解压缩”到主目录中。
这听起来像是tar命令的工作。但是假设您的用户不知道如何使用tar,或者他们在安装tarball文件时想要特殊选项(比如仅提取特定文件)。
另一个问题是您的.tar存档是一个二进制文件。如果您要通过电子邮件发送,必须使用Uuencode或Base64对其进行正确编码,以便安全传输。
该怎么办?不要扔掉.tar文件。相反,准备好它,以便您可以将其附加到Bash脚本(您将很快编写):
- $ base64 $tempdir/corona.tar.gz > $tempdir/corona_payload
- $ file $tempdir/corona_payload
- /tmp/tmp.8QNdzdKEkG/corona_payload: ASCII text
从.tar文件提取数据
您可以将所有内容倒到新目录中:
- $ newbase=$HOME/coronadata
- $ test ! -d $newbase && /bin/mkdir --parents --verbose $newbase
- $ tar --directory $newbase \
- --file corona.tar.gz --extract --gzip --verbose
也可以仅提取其中的一部分,比如措施、试验和测试目录。
- $ newbase=$HOME/coronadata
- $ test ! -d $newbase && /bin/mkdir --parents --verbose $newbase
- $ tar --directory $newbase --file corona.tar.gz \
- --extract --gzip --verbose measures experiment test
针对这次演练,将全部内容提取到基本目录(比如$HOME),因此结果如下:
- $HOME/$COVIDUSERDIR
剖析自解压脚本
以下是我的自解压脚本的代码。您可以将脚本保存在自己的Git存储库中,并重复用于其他部署环境。要注意的事项如下:
- SCRIPT_END是有效载荷在脚本里面开始的位置。
- 它净化用户输入。
- 一旦您搞清楚了元数据的位置,从脚本中提取($0),重新解码成二进制代码,然后拆包。
- #!/usr/bin/env bash
- # Author: Jose Vicente Nunez
- SCRIPT_END=$(/bin/grep --max-count 2 --line-number ___END_OF_SHELL_SCRIPT___ "$0"| /bin/cut --field 1 --delimiter :| /bin/tail -1)|| exit 100
- ((SCRIPT_END+=1))
- basedir=
- while test -z "$basedir"; do
- read -r -p "Where do you want to extract the COVID-19 data, relative to $HOME? (example: mydata -> $HOME/mydata. Press CTRL-C to abort):" basedir
- done
- :<








发表评论
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。