Contents

Linux二进制安装程序( .bin , .sh )如何工作?

1. 概述

二进制文件包含二进制数据,通常是机器可读的字节序列。有许多二进制格式,其中大多数是源代码的编译版本,这意味着它们是可执行的。另一方面,有些是不可执行的文件,如 BLOB(二进制大对象),可以包含图像、视频或任何丰富的多媒体对象。

.sh 文件也是可执行的。 .sh 文件是包含命令的 shell 脚本文件。 它们通常用于自动化操作,也可以用作安装程序。

2. Linux 中的二进制文件

二进制包是包含(预构建)可执行文件、从源代码构建且不可逆的应用程序包。二进制最重要的优点是能够隐藏源代码并防止将来修改。Linux 可以执行二进制文件,即使它有*.bin* 或任何文件名;扩展在某种程度上是无关紧要的。

在 Linux 系统中,二进制文件或包的标准目录是 /usr/bin, 其中可以找到大多数特定于系统的二进制文件。此外,  /user/local/bin 是保存非系统二进制文件(即本地编译或维护的包)的位置。但是,这两个目录都适用于所有系统范围的用户。对于特定用户,我们不应该在其中保留二进制文件,它的正确目录是 $HOME/bin 或 $HOME/.local/bin

2.1. 从源代码创建二进制文件

让我们创建一个应用程序并将其编译成二进制文件:

$ cat > demo.c <<EOF
#include <stdio.h>
    void main() {
    printf(“Hello World!\n”);
}
EOF

现在,我们将编译它:

$ gcc demo.c -o demo

编译成可执行二进制文件demo后,运行它:

$ ./demo
Hello, World!

如果源代码由一堆文件组成,如上所示编译将非常繁琐。对于这些情况,我们可以使用make  来自动化和管理构建过程。它需要一个包含一组任务的配置文件,称为 Makefile

2.2. 从*.sh*创建二进制 文件

Shell Script Compiler 或 SHC 是一种获取脚本并对其进行编码或加密的工具。这样, 它可以防止不必要的修改并隐藏源代码。我们将在示例中使用通用 shell 编译器  。还有许多其他工具可以编译或混淆脚本。

首先,让我们创建一个脚本 sum.sh 来返回输入数字的总和:

#!/bin/bash
total=0
for i in [[email protected]](/cdn_cgi/l/email_protection); do
    if [ ! -z “${i##[0-9]*}]; then
        echo “Please enter numeric only”
        exit 1
    fi
    total=$(($total + $i))
done
if [ $total -eq 0 ]; then
    echo “Plesae execute script like: $0 10 20 30”
    exit 0
fi
echo $total

在运行它之前,我们应该将其权限更改为可执行:

$ chmod +x sum.sh
$ ./sum.sh 8 9 10
27

接下来,让我们下载并安装最新版本的 SHC。然后编译脚本并将其转换为二进制:

$ shc -U -f sum.sh

它将创建两个新文件 sum.sh.xc(脚本的 C 语言版本)和 sum.sh.x(二进制版本)。现在,我们可以将 sum.sh.x 作为二进制文件执行:

$ mv sum.sh.x sum.bin
$ ./sum.bin

3. 自解压安装程序

通常,我们使用包管理器来安装、更新和删除包。它们使下载、提取和验证包的过程自动化。

但是,它们并不是管理安装的唯一方法。将二进制有效负载或存档文件添加到 shell 脚本是分发包的一种方法。 自解压安装程序会提取该有效负载并将内容复制到适当的位置。

在这里,我们将探索如何使用*.sh*文件作为安装程序。对于我们的示例,让我们创建一个包源:

$ mkdir demo-package && touch demo-package/demo-app.txt

然后构建并存档演示包:

$ tar -cvf archive.tar demo-package ; gzip -9 archive.tar

现在,让我们创建一个安装程序脚本 installer.sh

#!/bin/bash
function die() { echo "Error!"; exit 1; }
installer="$(pwd)/$(basename $BASH_SOURCE)"
cd ~/ || die
echo "Installing demo-app to ~/demo-app..."
archive=$(grep -a -n "__ARCHIVE_BELOW__:$" $installer | cut -f1 -d:)
echo $(tail -n +$((archive + 1)) $installer)
tail -n +$((archive + 1)) $installer | gzip -vdc - | tar -xvf - > /dev/null || die
# run some post installation if any
# ./app_name/bin/post_install_configuration.sh || die
echo "Installation complete!"
exit 0
__ARCHIVE_BELOW__:

然后将存档添加到installer.sh

$ cat archive.tar.gz >> installer.sh

现在使其可执行:

$ chmod +x installer.sh

最后,我们的安装程序已准备就绪。我们可以运行它来将我们的包安装到*~/*:

$ ./installer.sh

我们不建议在生产中使用此示例,因为它很容易受到恶意修改。此外,由于它们不使用包管理器,解决它们的依赖关系可能很麻烦,因此,一些这样的包使用静态链接的可执行文件,这意味着它们也添加了所有必要的库。与从包管理器安装相比,这些额外的库在使用时会浪费一些内存。

3.1.使用 makeself

我们还可以使用makeself 之类的命令行工具 来创建自解压安装程序。它有很多我们需要安装程序的选项。 它包括完整性和自我验证的校验和,这可以缓解我们之前示例中的主要安全漏洞。

语法:

$ makeself.sh [args] package_directory file_name label startup_script [script_args]

在此示例中,我们有一个包源 /demo-app  ,我们将创建一个名为 demo-pkg.run的安装程序:

$ makeself.sh --notemp ./demo-app ./demo-pkg.run "SFX archive for backup" echo "Extraction done"
Header is 715 lines long
About to compress 4 KB of data...
Adding files to archive named "./demo-pkg.run"...
./demo.txt
CRC: 3275129549
MD5: a718fbcfbb01730655ecaf5695dcb95b
Self-extractable archive "./demo-pkg.run" successfully created.
$ ./demo-pkg.run 
Creating directory demo-app
Verifying archive integrity...  100%   MD5 checksums are OK. All good.
Uncompressing SFX archive for backup  100%  
Extraction done

我们可以  用我们的启动脚本 替换echo “Extraction done”这个启动脚本可以做任何 shell 脚本可以对磁盘上的包文件做的任何事情;它可以将包移动到正确的目录。