@@ -41,9 +41,52 @@ func (a *HostAgent) waitForRequirements(label string, requirements []requirement
4141 return errors .Join (errs ... )
4242}
4343
44+ // prefixExportParam will modify a script to be executed by ssh.ExecuteScript so that it exports
45+ // all the variables from /mnt/lima-cidata/param.env before invoking the actual interpreter.
46+ //
47+ // - The script is executed in user mode, so needs to read the file using `sudo`.
48+ //
49+ // - `sudo cat param.env | while …; do export …; done` does not work because the piping
50+ // creates a subshell, and the exported variables are not visible to the parent process.
51+ //
52+ // - The `<<<"$string"` redirection is not available on alpine-lima, where /bin/bash is
53+ // just a wrapper around busybox ash.
54+ //
55+ // A script that will start with `#!/usr/bin/env ruby` will be modified to look like this:
56+ //
57+ // while read -r line; do
58+ // [ -n "$line" ] && export "$line"
59+ // done<<EOF
60+ // $(sudo cat /mnt/lima-cidata/param.env)
61+ // EOF
62+ // /usr/bin/env ruby
63+ //
64+ // ssh.ExecuteScript will strip the `#!` prefix from the first line and invoke the rest
65+ // of the line as the command. The full script is then passed via STDIN. We use the $' '
66+ // form of shell quoting to be able to use \n as newline escapes to fit everything on a
67+ // single line:
68+ //
69+ // #!/bin/bash -c $'while … done<<EOF\n$(sudo …)\nEOF\n/usr/bin/env ruby'
70+ // #!/usr/bin/env ruby
71+ // …
72+ func prefixExportParam (script string ) (string , error ) {
73+ interpreter , err := ssh .ParseScriptInterpreter (script )
74+ if err != nil {
75+ return "" , err
76+ }
77+
78+ // TODO we should have a symbolic constant for `/mnt/lima-cidata`
79+ exportParam := `while read -r line; do [ -n "$line" ] && export "$line"; done<<EOF\n$(sudo cat /mnt/lima-cidata/param.env)\nEOF\n`
80+ return fmt .Sprintf ("#!/bin/bash -c $'%s%s'\n %s" , exportParam , interpreter , script ), nil
81+ }
82+
4483func (a * HostAgent ) waitForRequirement (r requirement ) error {
4584 logrus .Debugf ("executing script %q" , r .description )
46- stdout , stderr , err := ssh .ExecuteScript (a .instSSHAddress , a .sshLocalPort , a .sshConfig , r .script , r .description )
85+ script , err := prefixExportParam (r .script )
86+ if err != nil {
87+ return err
88+ }
89+ stdout , stderr , err := ssh .ExecuteScript (a .instSSHAddress , a .sshLocalPort , a .sshConfig , script , r .description )
4790 logrus .Debugf ("stdout=%q, stderr=%q, err=%v" , stdout , stderr , err )
4891 if err != nil {
4992 return fmt .Errorf ("stdout=%q, stderr=%q: %w" , stdout , stderr , err )
0 commit comments