Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions reexec/example_multicall_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package reexec_test

import (
"fmt"
"os"

"github.com/moby/sys/reexec"
)

func init() {
reexec.Register("example-foo", func() {
fmt.Println("Hello from entrypoint example-foo")
})
reexec.Register("example-bar", func() {
fmt.Println("Hello from entrypoint example-bar")
})
}

// Example_multicall demonstrates a BusyBox-style multi-call binary.
//
// In a real multi-call binary:
//
// go build -o example .
// ln -s example example-foo
// ln -s example example-bar
//
// ./example-foo # runs entrypoint "example-foo"
// ./example-bar # runs entrypoint "example-bar"
//
// At process startup, main would call [reexec.Init] and return if it
// matches an entrypoint. This example first shows that call, then emulates
// different invocation names by modifying os.Args[0].
func Example_multicall() {
// What main would normally do:
if reexec.Init() {
// Matched a reexec entrypoint; stop normal main execution.
return
}
reset := os.Args[0]

// Emulate running as "example-foo".
os.Args[0] = "example-foo"
_ = reexec.Init()

// Emulate running as "example-bar".
os.Args[0] = "example-bar"
_ = reexec.Init()

// Emulate running under the default binary name (no match).
os.Args[0] = reset
if !reexec.Init() {
fmt.Println("Hello main")
}

// Output:
// Hello from entrypoint example-foo
// Hello from entrypoint example-bar
// Hello main
}
41 changes: 41 additions & 0 deletions reexec/example_programmatic_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package reexec_test

import (
"context"
"fmt"
"os"
"time"

"github.com/moby/sys/reexec"
)

func init() {
reexec.Register("example-child", func() {
fmt.Println("Hello from example-child entrypoint")
})
}

// Example_programmatic demonstrates using reexec to programmatically
// re-execute the current binary.
func Example_programmatic() {
if reexec.Init() {
// Matched a reexec entrypoint; stop normal main execution.
return
}

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

cmd := reexec.CommandContext(ctx, "example-child")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
fmt.Println("reexec error:", err)
return
}

fmt.Println("Back in parent process")
// Output:
// Hello from example-child entrypoint
// Back in parent process
}
Loading