How do Linux binary installers (.bin, .sh) work?
Basically, it's a shell script prepended to a compressed archive of some sort, such as a tar archive. You use the tail
or sed
command on yourself (the $0
variable in Bourne shell) to strip off the shell script at the front and pass the rest to your unarchiver.
For example, create the following script as self-extracting
:
#!/bin/sh -e
sed -e '1,/^exit$/d' "$0" | tar xzf - && ./project/Setup
exit
The sed
command above deletes all lines from the first line of the file to the first one that starts with "exit", and then passes the rest on through. If what starts immediately after the "exit" line is a tar file, the tar
command will extract it. If that's successful, the ./project/Setup
file (presumably extracted from the tarball) will be executed.
Then:
mkdir project
echo "#!/bin/sh" > project/Setup
echo "echo This is the setup script!" >> project/Setup
chmod +x project/Setup
tar czf - project >> self-extracting
Now, if you get rid of your old project
directory, you can run self-extracting
and it will extract that tar file and run the setup script.
What’s the best way to distribute a binary application for Linux?
Having been through this a couple of times with commercial products, I think the very best answer is to use the native installer for each supported platform. Anything else produces an unpleasant experience for the end-user, and in practice you have to test on every platform you want to support anyway, so it's not really a significant burden to maintain packages for each. The idea that you can create a binary that can "just work" on every platform out there, including some you've never even heard of, just really doesn't work all that well.
My recommendation is that you pick a platform or two to support initially (Red Hat and Ubuntu would be my suggestions) and then let user demand drive the creation of additional installation packages. Perhaps make it known that you're willing to support additional platforms, for a modest fee that covers your time and effort in packaging and testing on that platform. If a platform proves to be very different, you may need to charge more for ongoing support.
Oh, and I cannot overemphasize the value of virtual machines for scenarios like this. You need to build VMs for each platform you support, and perhaps multiple VMs per platform to make it easy to test different configurations.
Distributing binary applications across linux distros
RPM and DEB packages are the two primary mechanisms for distributing binary packages in Linux. RPM is used by RedHat and its derivatives (Fedora, CentOS), while DEB is used in Debian and Ubuntu.
The .rpm and .deb files themselves are generally "dumb" archives, and are installed to the correct locations in the filesystem by pre-installed helper applications. You don't have to worry about writing scripts to install files, unless it's a very complicated application which needs special per-system configuration.
The usual patterns I see for distributing binaries are:
- Release a compessed tarball (.tar.gz or .tar.bz2), and let distribution packagers worry about the details. This works well for popular applications, but if it's newly released, nobody will care enough about your application to package it.
- Release as a tarball, plus RPM and/or DEB packages (depending on customer needs). Customers with a supported distribution may install the pre-made package. Anybody who's using an unusual distribution is probably happy to install from a tarball anyway.
Create binaries that run on all Linux distrubtion
The packages that you're referring to ... a ".run" or a ".sh" are just scripts. Since people tend to want to 'just get the installation started' and could click on the wrong package, a shell script can detect what package would be appropriate, download and install it.
Or potentially even download and build the source ... somewhat depends on the project and aim of the package.
Can I mix text with binary in linux?
Perfectly feasible.
Example: http://www.stuartwells.net/slides/selfextract.htm
Bash script containing binary executable
i never done something like this before ;)
this will compile some c source, create a b.bash
script containing the binary (and the original script for simple development)
(a.bash)
#!/bin/bash
if [ "$0" == "b.bash" ];then
tail -n +$[ `grep -n '^BINARY' $0|cut -d ':' -f 1` + 1 ] $0 | base64 -d > a2.out
chmod +x a2.out
./a2.out
echo $?
exit
fi
cat "$0" > b.bash
echo "BINARY" >> b.bash
cat > a.c << EOF
int main(){
return 12;
}
EOF
gcc a.c
base64 a.out >> b.bash
invoke with (a.bash generates b.bash):
bash a.bash ;bash b.bash
i don't know how to evade writing out the binary into a temporary file before execution...
cannot execute binary file when trying to run a shell script on linux
chmod -x
removes execution permission from a file. Do this:
chmod +x path/to/mynewshell.sh
And run it with
/path/to/mynewshell.sh
As the error report says, you script is not actually a script, it's a binary file.
Related Topics
How to Recursively Find All Files in Current and Subfolders Based on Wildcard Matching
What Does "&" At the End of a Linux Command Mean
How to Merge Two Files Using Awk
What Does $@ Mean in a Shell Script
Fastest Way to Find Lines of a File from Another Larger File in Bash
Peak Memory Usage of a Linux/Unix Process
Retaining File Permissions With Git
How to Print a Number in Assembly Nasm
Simulate Delayed and Dropped Packets on Linux
The 'Eval' Command in Bash and Its Typical Uses
Does Malloc Lazily Create the Backing Pages For an Allocation on Linux (And Other Platforms)
Use Bluez Stack as a Peripheral (Advertiser)
Externalizing Tomcat Webapp Config from .War File
Bash Alias Command With Both Single and Double Quotes
Maximum Length of Command Line Argument That Can Be Passed to Sql*Plus