Files
exec/README.md
T

195 lines
4.9 KiB
Markdown

# go-bds exec
Go library for running commands in different environments: `host`, `Docker`, `SSH`, and `proot`.
The package exposes a common process interface and a few `rootfs` helpers for copying, importing, and exporting filesystems across those environments.
## What this package provides
- Unified process interface: `process.Proc`
- Standard command struct: `process.Exec`
- Execution backends:
- `host` / `os`
- `docker`
- `proot`
- `ssh`
- `rootfs` implementations:
- `host.Rootfs`
- `docker.Rootfs`
- `ssh.Rootfs`
- `proot` extensions:
- `bind`
- `fs`
- `overlayfs`
- `qemu`
- Utility for downloading OCI/Docker images directly from a registry without depending on the local daemon:
- `tools/local_extract_registry`
## Requirements
- Go `1.25` or newer
- A reachable Docker daemon for the `docker` backend and `docker.Rootfs`
- Valid SSH access for `ssh.Rootfs` and `ssh.Session`
- Linux or Android for the pure-Go `proot` backend
## Installation
```bash
go get sirherobrine23.com.br/go-bds/exec/v2
```
## Basic usage
```go
package main
import (
"log"
"os"
"sirherobrine23.com.br/go-bds/exec/v2/host"
"sirherobrine23.com.br/go-bds/exec/v2/process"
)
func main() {
proc, err := host.NewProc()
if err != nil {
log.Fatal(err)
}
defer proc.Close()
_ = proc.AttachStdout(os.Stdout)
_ = proc.AttachStderr(os.Stderr)
err = proc.Start(&process.Exec{
Arguments: []string{"sh", "-lc", "echo hello"},
})
if err != nil {
log.Fatal(err)
}
if err := proc.Wait(); err != nil {
log.Fatal(err)
}
}
```
## Using the process registry
Backends are registered by name when their packages are imported.
```go
import (
_ "sirherobrine23.com.br/go-bds/exec/v2/docker"
_ "sirherobrine23.com.br/go-bds/exec/v2/host"
_ "sirherobrine23.com.br/go-bds/exec/v2/proot"
"sirherobrine23.com.br/go-bds/exec/v2/process"
)
proc, err := process.ReturnNewProcess("host", &process.Exec{
Arguments: []string{"sh", "-lc", "id"},
})
```
Registered process names:
- `host`
- `os`
- `docker`
- `proot`
## Backends
### `host`
Runs the command on the local operating system. `host.Os` accepts `SysProcAttr` and an optional `Rootfs` used to prefix the working directory.
### `docker`
Runs the command inside a Docker container. `docker.DockerContainer` lets you configure image, platform, ports, and volumes.
### `ssh`
Runs commands in an SSH session. `ssh.Session` can be created from an existing `ssh.Client` or through helpers such as `ssh.NewClientPassword`.
### `proot`
Pure-Go backend for Linux/Android, without depending on the external `proot` binary. It uses `ptrace` to remap path-based system calls and supports:
- `rootfs` remapping
- host-to-guest bind mappings
- `cwd` and `PATH` resolution
- `execve`, `openat`, `stat`, `access`, `readlink`, `chdir`, and common path mutations
Example:
```go
import (
"sirherobrine23.com.br/go-bds/exec/v2/process"
"sirherobrine23.com.br/go-bds/exec/v2/proot"
)
proc := &proot.Proot{
Rootfs: "/tmp/rootfs",
Binds: map[string][]string{
"/dev": {"/dev"},
},
DefaultBinds: []string{"/dev"},
}
err := proc.Start(&process.Exec{
Arguments: []string{"/bin/sh", "-lc", "echo inside proot"},
})
```
`proot` also exposes `AddNameservers`, which writes entries into `etc/resolv.conf` inside the `rootfs`.
## `proot` extensions
Extensions live under `proot/extensions` and are applied before the process starts.
- `bind`: exposes host paths inside the guest
- `fs`: adds an `io/fs.FS` as a read-only tree
- `overlayfs`: adds overlay semantics with upper/lower layers and whiteouts
- `qemu`: redirects execution to a `qemu-*` emulator when needed
Extensions are applied in order and can adjust `Rootfs`, `Binds`, `DefaultBinds`, path resolvers, and exec resolvers.
## Rootfs
`rootfs` types implement `process.Rootfs` and let you create processes from a filesystem source.
- `host.Rootfs`:
- works on a local directory
- supports tar import and export
- can use `chroot` when requested
- `docker.Rootfs`:
- exports and imports images through Docker
- creates a `docker.DockerContainer` for execution
- `ssh.Rootfs`:
- synchronizes files over SFTP
- creates an `ssh.Session` for remote execution
## Registry utility
`tools/local_extract_registry.PullImage` downloads an OCI/Docker image and extracts its layers directly into a local directory.
This is useful when you want to build a `rootfs` without depending on the local Docker daemon.
## Module layout
- `process`: process and rootfs types plus registries
- `host`: local execution and local rootfs
- `docker`: container execution and Docker-backed rootfs
- `ssh`: remote execution and SSH/SFTP-backed rootfs
- `proot`: pure-Go backend and extensions
- `tools/local_extract_registry`: registry image extraction
## Notes
- The `proot` backend is specific to Linux/Android.
- The `docker` backend depends on the Docker daemon and the current user's permissions.
- The `ssh` backend assumes the remote server accepts interactive and `exec` sessions.