Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # Self-Extracting Binary Guide
- ## What is This?
- A **self-extracting binary** is a single file that:
- 1. Contains compressed data (your files)
- 2. Is executable like a program
- 3. Extracts itself to a temp directory
- 4. Runs your application
- 5. Cleans up when done
- ## How It Works (Step by Step)
- ### 1. The Archive Structure
- ```
- +----------------------------------+
- | #!/bin/sh | <-- Shell script header
- | (extraction code) |
- +----------------------------------+
- | GZIPPED DATA | <-- Your files compressed
- | (binaries, configs, etc.) |
- +----------------------------------+
- | CRC checksum | <-- Integrity check
- +----------------------------------+
- ```
- ### 2. Execution Flow
- When user runs `./myapp.run`:
- 1. **Shell interprets** the header script
- 2. **Extracts** compressed data to `/tmp/selfextract.XXXX/`
- 3. **Changes** to that directory
- 4. **Executes** your entrypoint script
- 5. **Returns** to original directory
- 6. **Cleans up** temp files (unless --notemp)
- ## The `makeself` Command
- ### Basic Syntax
- ```bash
- makeself [options] <source_dir> <output_file> <label> <entrypoint>
- ```
- ### Arguments Explained
- | Argument | Description | Example |
- |----------|-------------|---------|
- | `source_dir` | Directory to pack | `./dist` or `.` |
- | `output_file` | Output filename | `./myapp.run` |
- | `label` | Description shown during extraction | `"My App v1.0"` |
- | `entrypoint` | Command to run after extract | `./start.sh` |
- ### Common Options
- ```bash
- # Compression options
- --gzip # Fast compression (default)
- --bzip2 # Better compression
- --xz # Best compression (slowest)
- # Behavior options
- --notemp # Don't use temp dir (extract in place)
- --nox11 # Disable X11 forwarding
- --quiet # Minimal output
- # Checksum options
- --sha256 # Use SHA256 instead of CRC
- ```
- ## Examples
- ### Example 1: Simple Python App
- ```bash
- # Project structure:
- # myapp/
- # ├── main.py
- # └── config.json
- makeself ./myapp ./myapp.run "My Python App" "python3 ./main.py"
- ```
- ### Example 2: Complex Project with Launcher
- ```bash
- # Project structure:
- # myapp/
- # ├── bin/
- # │ └── mybinary
- # ├── data/
- # │ └── assets/
- # └── start.sh
- # Create launcher (start.sh):
- #!/bin/bash
- cd "$(dirname "$0")"
- ./bin/mybinary "$@"
- # Build:
- makeself --gzip ./myapp ./myapp.run "My App v1.0" "./start.sh"
- ```
- ### Example 3: With Dependencies
- ```bash
- # For projects needing system deps, check first:
- #!/bin/bash
- # launcher.sh
- cd "$(dirname "$0")"
- # Check dependencies
- if ! command -v python3 &> /dev/null; then
- echo "Error: python3 not installed"
- exit 1
- fi
- # Run app
- python3 ./main.py "$@"
- ```
- ## Advanced Usage
- ### Passing Arguments Through
- Your entrypoint receives all arguments:
- ```bash
- # start.sh
- #!/bin/bash
- cd "$(dirname "$0")"
- ./myapp "$@" # Pass all args to actual app
- ```
- Then run:
- ```bash
- ./myapp.run --help # Passes --help to myapp
- ./myapp.run -v -c file # Passes all args
- ```
- ### Runtime Options (Built-in)
- Self-extracting archives have these automatic options:
- ```bash
- ./myapp.run --check # Verify archive integrity
- ./myapp.run --list # List files in archive
- ./myapp.run --target /path # Extract to specific directory
- ./myapp.run --noexec # Extract but don't run
- ./myapp.run --verbose # Show extraction details
- ```
- ### Not Extracting to Temp
- Use `--notemp` to extract in current directory:
- ```bash
- makeself --notemp ./src ./installer.run "Installer" "./install.sh"
- ```
- This creates a hidden directory `.selfextract-XXXX` that gets cleaned up.
- ## Build Scripts
- ### Minimal Build Script
- ```bash
- #!/bin/bash
- set -e
- # Clean build
- rm -rf build
- mkdir build
- # Copy files
- cp -r src/* build/
- # Make launcher executable
- chmod +x build/start.sh
- # Build
- makeself build myapp.run "My App" ./start.sh
- # Clean
- rm -rf build
- echo "Built: myapp.run"
- ```
- ### Full-Featured Build Script
- See `makeself-packer.sh` in this directory for a complete,
- configurable build script with:
- - Command-line options
- - Error handling
- - Progress logging
- - Compression selection
- ## Compression Comparison
- | Method | Speed | Size | Use Case |
- |--------|-------|------|----------|
- | gzip | Fast | ~70% | Default, good balance |
- | bzip2 | Slow | ~60% | Smaller files |
- | xz | Slowest | ~55% | Maximum compression |
- Test with your data:
- ```bash
- makeself --gzip ./src ./app-gzip.run "Test" ./start.sh
- makeself --xz ./src ./app-xz.run "Test" ./start.sh
- ls -lh app-*.run # Compare sizes
- ```
- ## Troubleshooting
- ### "Permission denied" when running
- ```bash
- chmod +x myapp.run
- ```
- ### Archive too big
- ```bash
- # Use better compression
- makeself --xz ./src ./app.run "App" ./start.sh
- # Or exclude unnecessary files
- rm -rf src/tests src/docs
- makeself ./src ./app.run "App" ./start.sh
- ```
- ### "Command not found" after extraction
- ```bash
- # Make sure your entrypoint exists in source
- # and has proper shebang (#!/bin/bash)
- # Verify:
- head -1 start.sh
- # Should output: #!/bin/bash
- ```
- ### Path issues in entrypoint
- ```bash
- # Always use this pattern in your launcher:
- cd "$(dirname "$(readlink -f "$0")")" || exit 1
- # This works even if script is symlinked
- ```
- ## Installation
- ### For Current User
- ```bash
- cp myapp.run ~/.local/bin/myapp
- chmod +x ~/.local/bin/myapp
- # Make sure ~/.local/bin is in your $PATH
- ```
- ### System-Wide
- ```bash
- sudo cp myapp.run /usr/local/bin/myapp
- sudo chmod +x /usr/local/bin/myapp
- ```
- ### Create Desktop Entry (Linux)
- ```bash
- # ~/.local/share/applications/myapp.desktop
- cat > ~/.local/share/applications/myapp.desktop << EOF
- [Desktop Entry]
- Name=My Application
- Exec=/home/username/.local/bin/myapp
- Icon=/path/to/icon.png
- Type=Application
- Terminal=true
- EOF
- ```
- ## How to Unpack (Reverse)
- If you need to extract without running:
- ```bash
- # Method 1: Use built-in option
- ./myapp.run --noexec --target ./extracted
- # Method 2: Manually (skip first N lines)
- tail -n +$(( $(grep -n "^exit 0$" myapp.run | head -1 | cut -d: -f1) + 1 )) myapp.run > data.tar.gz
- gunzip data.tar.gz
- tar -xf data.tar
- # Method 3: Run with trace to see where it extracts
- bash -x ./myapp.run 2>&1 | grep "selfextract"
- ```
- ## References
- - **makeself**: https://makeself.io/
- - **GitHub**: https://github.com/megastep/makeself
- - **Man page**: `man makeself`
Advertisement
Add Comment
Please, Sign In to add comment