checkpoint, switch name from sh2-runner to mshell

This commit is contained in:
sawka
2022-06-23 10:16:54 -07:00
parent 0b172cd689
commit 766d19f1bc
7 changed files with 152 additions and 95 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
module github.com/scripthaus-dev/sh2-runner module github.com/scripthaus-dev/mshell
go 1.17 go 1.17
+5 -5
View File
@@ -15,10 +15,10 @@ import (
"time" "time"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/scripthaus-dev/sh2-runner/pkg/base" "github.com/scripthaus-dev/mshell/pkg/base"
"github.com/scripthaus-dev/sh2-runner/pkg/cmdtail" "github.com/scripthaus-dev/mshell/pkg/cmdtail"
"github.com/scripthaus-dev/sh2-runner/pkg/packet" "github.com/scripthaus-dev/mshell/pkg/packet"
"github.com/scripthaus-dev/sh2-runner/pkg/shexec" "github.com/scripthaus-dev/mshell/pkg/shexec"
) )
// in single run mode, we don't want the runner to die from signals // in single run mode, we don't want the runner to die from signals
@@ -155,7 +155,7 @@ func doMain() {
packet.SendErrorPacket(os.Stdout, fmt.Sprintf("cannot change directory to $HOME '%s': %v", homeDir, err)) packet.SendErrorPacket(os.Stdout, fmt.Sprintf("cannot change directory to $HOME '%s': %v", homeDir, err))
return return
} }
err = base.EnsureRunnerPath() err = base.EnsureMShellPath()
if err != nil { if err != nil {
packet.SendErrorPacket(os.Stdout, err.Error()) packet.SendErrorPacket(os.Stdout, err.Error())
return return
+12 -22
View File
@@ -11,11 +11,14 @@ import (
"fmt" "fmt"
"io/fs" "io/fs"
"os" "os"
"os/exec"
"path" "path"
"path/filepath" "path/filepath"
) )
const ScRunnerVarName = "SCRIPTHAUS_RUNNER" const DefaultMShellPath = "mshell"
const MShellPathVarName = "MSHELL_PATH"
const SSHCommandVarName = "SSH_COMMAND"
const ScHomeVarName = "SCRIPTHAUS_HOME" const ScHomeVarName = "SCRIPTHAUS_HOME"
const HomeVarName = "HOME" const HomeVarName = "HOME"
const ScShell = "bash" const ScShell = "bash"
@@ -125,33 +128,20 @@ func EnsureSessionDir(sessionId string) (string, error) {
return sdir, nil return sdir, nil
} }
func GetScRunnerPath() (string, error) { func GetMShellPath() string {
runnerPath := os.Getenv(ScRunnerVarName) msPath := os.Getenv(MShellPathVarName)
if runnerPath != "" { if msPath != "" {
return runnerPath, nil return msPath
} }
scHome, err := GetScHomeDir() return DefaultMShellPath
if err != nil {
return "", err
}
return path.Join(scHome, RunnerBaseName), nil
} }
func EnsureRunnerPath() error { func EnsureMShellPath() error {
runnerPath, err := GetScRunnerPath() msPath := GetMShellPath()
_, err := exec.LookPath(msPath)
if err != nil { if err != nil {
return err return err
} }
info, err := os.Stat(runnerPath)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
return fmt.Errorf("cannot find scripthaus runner at path '%s'", runnerPath)
}
return fmt.Errorf("error stating scripthaus runner at path '%s'", runnerPath)
}
if info.Mode()&0100 == 0 {
return fmt.Errorf("scripthaus runner at path '%s' is not executable mode=%#o", runnerPath, info.Mode())
}
return nil return nil
} }
+2 -2
View File
@@ -16,8 +16,8 @@ import (
"github.com/fsnotify/fsnotify" "github.com/fsnotify/fsnotify"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/scripthaus-dev/sh2-runner/pkg/base" "github.com/scripthaus-dev/mshell/pkg/base"
"github.com/scripthaus-dev/sh2-runner/pkg/packet" "github.com/scripthaus-dev/mshell/pkg/packet"
) )
const MaxDataBytes = 4096 const MaxDataBytes = 4096
+34
View File
@@ -0,0 +1,34 @@
package packet
type CombinedPacket struct {
Type string `json:"type"`
Success bool `json:"success"`
Ts int64 `json:"ts"`
Id string `json:"id,omitempty"`
SessionId string `json:"sessionid"`
CmdId string `json:"cmdid"`
PtyPos int64 `json:"ptypos"`
PtyLen int64 `json:"ptylen"`
RunPos int64 `json:"runpos"`
RunLen int64 `json:"runlen"`
Error string `json:"error"`
NotFound bool `json:"notfound,omitempty"`
Tail bool `json:"tail,omitempty"`
Dir string `json:"dir"`
ChDir string `json:"chdir,omitempty"`
Data string `json:"data"`
PtyData string `json:"ptydata"`
RunData string `json:"rundata"`
Message string `json:"message"`
Command string `json:"command"`
ScHomeDir string `json:"schomedir"`
HomeDir string `json:"homedir"`
Env []string `json:"env"`
ExitCode int `json:"exitcode"`
RunnerPid int `json:"runnerpid"`
}
+84 -48
View File
@@ -18,22 +18,29 @@ import (
"sync" "sync"
) )
const RunPacketStr = "run" // remote: runnerinit, run, ping, data, cmdstart, cmddone
const PingPacketStr = "ping" // remote(detached): runnerinit, run, cmdstart
const DonePacketStr = "done" // server: runnerinit, run, ping, cmdstart, cmddone, cd, resp, getcmd, untailcmd, cmddata, input, data, [comp]
const ErrorPacketStr = "error" // all: error, message
const MessagePacketStr = "message"
const CmdStartPacketStr = "cmdstart" const (
const CmdDonePacketStr = "cmddone" RunPacketStr = "run"
const ListCmdPacketStr = "lscmd" PingPacketStr = "ping"
const GetCmdPacketStr = "getcmd" RunnerInitPacketStr = "runnerinit"
const UntailCmdPacketStr = "untailcmd" DataPacketStr = "data"
const RunnerInitPacketStr = "runnerinit" CmdStartPacketStr = "cmdstart"
const CdPacketStr = "cd" CmdDonePacketStr = "cmddone"
const CdResponseStr = "cdresp" ResponsePacketStr = "resp"
const CmdDataPacketStr = "cmddata" DonePacketStr = "done"
const RawPacketStr = "raw" ErrorPacketStr = "error"
const InputPacketStr = "input" MessagePacketStr = "message"
GetCmdPacketStr = "getcmd"
UntailCmdPacketStr = "untailcmd"
CdPacketStr = "cd"
CmdDataPacketStr = "cmddata"
RawPacketStr = "raw"
InputPacketStr = "input"
)
var TypeStrToFactory map[string]reflect.Type var TypeStrToFactory map[string]reflect.Type
@@ -41,20 +48,20 @@ func init() {
TypeStrToFactory = make(map[string]reflect.Type) TypeStrToFactory = make(map[string]reflect.Type)
TypeStrToFactory[RunPacketStr] = reflect.TypeOf(RunPacketType{}) TypeStrToFactory[RunPacketStr] = reflect.TypeOf(RunPacketType{})
TypeStrToFactory[PingPacketStr] = reflect.TypeOf(PingPacketType{}) TypeStrToFactory[PingPacketStr] = reflect.TypeOf(PingPacketType{})
TypeStrToFactory[ResponsePacketStr] = reflect.TypeOf(ResponsePacketType{})
TypeStrToFactory[DonePacketStr] = reflect.TypeOf(DonePacketType{}) TypeStrToFactory[DonePacketStr] = reflect.TypeOf(DonePacketType{})
TypeStrToFactory[ErrorPacketStr] = reflect.TypeOf(ErrorPacketType{}) TypeStrToFactory[ErrorPacketStr] = reflect.TypeOf(ErrorPacketType{})
TypeStrToFactory[MessagePacketStr] = reflect.TypeOf(MessagePacketType{}) TypeStrToFactory[MessagePacketStr] = reflect.TypeOf(MessagePacketType{})
TypeStrToFactory[CmdStartPacketStr] = reflect.TypeOf(CmdStartPacketType{}) TypeStrToFactory[CmdStartPacketStr] = reflect.TypeOf(CmdStartPacketType{})
TypeStrToFactory[CmdDonePacketStr] = reflect.TypeOf(CmdDonePacketType{}) TypeStrToFactory[CmdDonePacketStr] = reflect.TypeOf(CmdDonePacketType{})
TypeStrToFactory[ListCmdPacketStr] = reflect.TypeOf(ListCmdPacketType{})
TypeStrToFactory[GetCmdPacketStr] = reflect.TypeOf(GetCmdPacketType{}) TypeStrToFactory[GetCmdPacketStr] = reflect.TypeOf(GetCmdPacketType{})
TypeStrToFactory[UntailCmdPacketStr] = reflect.TypeOf(UntailCmdPacketType{}) TypeStrToFactory[UntailCmdPacketStr] = reflect.TypeOf(UntailCmdPacketType{})
TypeStrToFactory[RunnerInitPacketStr] = reflect.TypeOf(RunnerInitPacketType{}) TypeStrToFactory[RunnerInitPacketStr] = reflect.TypeOf(RunnerInitPacketType{})
TypeStrToFactory[CdPacketStr] = reflect.TypeOf(CdPacketType{}) TypeStrToFactory[CdPacketStr] = reflect.TypeOf(CdPacketType{})
TypeStrToFactory[CdResponseStr] = reflect.TypeOf(CdResponseType{})
TypeStrToFactory[CmdDataPacketStr] = reflect.TypeOf(CmdDataPacketType{}) TypeStrToFactory[CmdDataPacketStr] = reflect.TypeOf(CmdDataPacketType{})
TypeStrToFactory[RawPacketStr] = reflect.TypeOf(RawPacketType{}) TypeStrToFactory[RawPacketStr] = reflect.TypeOf(RawPacketType{})
TypeStrToFactory[InputPacketStr] = reflect.TypeOf(InputPacketType{}) TypeStrToFactory[InputPacketStr] = reflect.TypeOf(InputPacketType{})
TypeStrToFactory[DataPacketStr] = reflect.TypeOf(DataPacketType{})
} }
func MakePacket(packetType string) (PacketType, error) { func MakePacket(packetType string) (PacketType, error) {
@@ -103,6 +110,22 @@ func MakePingPacket() *PingPacketType {
return &PingPacketType{Type: PingPacketStr} return &PingPacketType{Type: PingPacketStr}
} }
type DataPacketType struct {
Type string `json:"type"`
SessionId string `json:"sessionid"`
CmdId string `json:"cmdid"`
FdNum int `json:"fdnum"`
Data string `json:"data"`
}
func (*DataPacketType) GetType() string {
return DataPacketStr
}
func MakeDataPacket(fdNum int, data string) *DataPacketType {
return &DataPacketType{Type: DataPacketStr, FdNum: fdNum, Data: data}
}
// InputData gets written to PTY directly // InputData gets written to PTY directly
// SigNum gets sent to process via a signal // SigNum gets sent to process via a signal
// WinSize, if set, will run TIOCSWINSZ to set size, and then send SIGWINCH // WinSize, if set, will run TIOCSWINSZ to set size, and then send SIGWINCH
@@ -157,19 +180,6 @@ func MakeGetCmdPacket() *GetCmdPacketType {
return &GetCmdPacketType{Type: GetCmdPacketStr} return &GetCmdPacketType{Type: GetCmdPacketStr}
} }
type ListCmdPacketType struct {
Type string `json:"type"`
SessionId string `json:"sessionid"`
}
func (*ListCmdPacketType) GetType() string {
return ListCmdPacketStr
}
func MakeListCmdPacket(sessionId string) *ListCmdPacketType {
return &ListCmdPacketType{Type: ListCmdPacketStr, SessionId: sessionId}
}
type CdPacketType struct { type CdPacketType struct {
Type string `json:"type"` Type string `json:"type"`
PacketId string `json:"packetid"` PacketId string `json:"packetid"`
@@ -180,23 +190,32 @@ func (*CdPacketType) GetType() string {
return CdPacketStr return CdPacketStr
} }
func (p *CdPacketType) GetPacketId() string {
return p.PacketId
}
func MakeCdPacket() *CdPacketType { func MakeCdPacket() *CdPacketType {
return &CdPacketType{Type: CdPacketStr} return &CdPacketType{Type: CdPacketStr}
} }
type CdResponseType struct { type ResponsePacketType struct {
Type string `json:"type"` Type string `json:"type"`
PacketId string `json:"packetid"` PacketId string `json:"packetid"`
Success bool `json:"success"` Success bool `json:"success"`
Error string `json:"error"` Error string `json:"error"`
Data interface{} `json:"data"`
} }
func (*CdResponseType) GetType() string { func (*ResponsePacketType) GetType() string {
return CdResponseStr return ResponsePacketStr
} }
func MakeCdResponse() *CdResponseType { func (p *ResponsePacketType) GetPacketId() string {
return &CdResponseType{Type: CdResponseStr} return p.PacketId
}
func MakeResponsePacket(packetId string) *ResponsePacketType {
return &ResponsePacketType{Type: ResponsePacketStr, PacketId: packetId}
} }
type RawPacketType struct { type RawPacketType struct {
@@ -232,10 +251,11 @@ func FmtMessagePacket(fmtStr string, args ...interface{}) *MessagePacketType {
type RunnerInitPacketType struct { type RunnerInitPacketType struct {
Type string `json:"type"` Type string `json:"type"`
ScHomeDir string `json:"schomedir"` Version string `json:"version"`
HomeDir string `json:"homedir"` ScHomeDir string `json:"schomedir,omitempty"`
Env []string `json:"env"` HomeDir string `json:"homedir,omitempty"`
User string `json:"user"` Env []string `json:"env,omitempty"`
User string `json:"user,omitempty"`
} }
func (*RunnerInitPacketType) GetType() string { func (*RunnerInitPacketType) GetType() string {
@@ -290,15 +310,26 @@ func MakeCmdStartPacket() *CmdStartPacketType {
return &CmdStartPacketType{Type: CmdStartPacketStr} return &CmdStartPacketType{Type: CmdStartPacketStr}
} }
type TermSize struct {
Rows int `json:"rows"`
Cols int `json:"cols"`
}
type RemoteFd struct {
FdNum int `json:"fdnum"`
Read bool `json:"read"`
Write bool `json:"write"`
}
type RunPacketType struct { type RunPacketType struct {
Type string `json:"type"` Type string `json:"type"`
SessionId string `json:"sessionid"` SessionId string `json:"sessionid"`
CmdId string `json:"cmdid"` CmdId string `json:"cmdid"`
ChDir string `json:"chdir,omitempty"`
Env map[string]string `json:"env,omitempty"`
Command string `json:"command"` Command string `json:"command"`
Rows int `json:"rows"` Cwd string `json:"cwd,omitempty"`
Cols int `json:'cols"` Env map[string]string `json:"env,omitempty"`
TermSize TermSize `json:"termsize"`
Fds []RemoteFd `json:"fds"`
} }
func (*RunPacketType) GetType() string { func (*RunPacketType) GetType() string {
@@ -335,6 +366,11 @@ type PacketType interface {
GetType() string GetType() string
} }
type RpcPacketType interface {
GetType() string
GetPacketId() string
}
func ParseJsonPacket(jsonBuf []byte) (PacketType, error) { func ParseJsonPacket(jsonBuf []byte) (PacketType, error) {
var bareCmd BarePacketType var bareCmd BarePacketType
err := json.Unmarshal(jsonBuf, &bareCmd) err := json.Unmarshal(jsonBuf, &bareCmd)
+14 -17
View File
@@ -17,8 +17,8 @@ import (
"github.com/creack/pty" "github.com/creack/pty"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/scripthaus-dev/sh2-runner/pkg/base" "github.com/scripthaus-dev/mshell/pkg/base"
"github.com/scripthaus-dev/sh2-runner/pkg/packet" "github.com/scripthaus-dev/mshell/pkg/packet"
) )
const DefaultRows = 25 const DefaultRows = 25
@@ -79,8 +79,8 @@ func UpdateCmdEnv(cmd *exec.Cmd, envVars map[string]string) {
func MakeExecCmd(pk *packet.RunPacketType, cmdTty *os.File) *exec.Cmd { func MakeExecCmd(pk *packet.RunPacketType, cmdTty *os.File) *exec.Cmd {
ecmd := exec.Command("bash", "-c", pk.Command) ecmd := exec.Command("bash", "-c", pk.Command)
UpdateCmdEnv(ecmd, pk.Env) UpdateCmdEnv(ecmd, pk.Env)
if pk.ChDir != "" { if pk.Cwd != "" {
ecmd.Dir = pk.ChDir ecmd.Dir = pk.Cwd
} }
ecmd.Stdin = cmdTty ecmd.Stdin = cmdTty
ecmd.Stdout = cmdTty ecmd.Stdout = cmdTty
@@ -93,11 +93,8 @@ func MakeExecCmd(pk *packet.RunPacketType, cmdTty *os.File) *exec.Cmd {
} }
func MakeRunnerExec(cmdId string) (*exec.Cmd, error) { func MakeRunnerExec(cmdId string) (*exec.Cmd, error) {
runnerPath, err := base.GetScRunnerPath() msPath := base.GetMShellPath()
if err != nil { ecmd := exec.Command(msPath, cmdId)
return nil, err
}
ecmd := exec.Command(runnerPath, cmdId)
return ecmd, nil return ecmd, nil
} }
@@ -141,13 +138,13 @@ func ValidateRunPacket(pk *packet.RunPacketType) error {
if err != nil { if err != nil {
return fmt.Errorf("invalid cmdid '%s' for command", pk.CmdId) return fmt.Errorf("invalid cmdid '%s' for command", pk.CmdId)
} }
if pk.ChDir != "" { if pk.Cwd != "" {
dirInfo, err := os.Stat(pk.ChDir) dirInfo, err := os.Stat(pk.Cwd)
if err != nil { if err != nil {
return fmt.Errorf("invalid cwd '%s' for command: %v", pk.ChDir, err) return fmt.Errorf("invalid cwd '%s' for command: %v", pk.Cwd, err)
} }
if !dirInfo.IsDir() { if !dirInfo.IsDir() {
return fmt.Errorf("invalid cwd '%s' for command, not a directory", pk.ChDir) return fmt.Errorf("invalid cwd '%s' for command, not a directory", pk.Cwd)
} }
} }
return nil return nil
@@ -156,11 +153,11 @@ func ValidateRunPacket(pk *packet.RunPacketType) error {
func GetWinsize(p *packet.RunPacketType) *pty.Winsize { func GetWinsize(p *packet.RunPacketType) *pty.Winsize {
rows := DefaultRows rows := DefaultRows
cols := DefaultCols cols := DefaultCols
if p.Rows > 0 && p.Rows <= MaxRows { if p.TermSize.Rows > 0 && p.TermSize.Rows <= MaxRows {
rows = p.Rows rows = p.TermSize.Rows
} }
if p.Cols > 0 && p.Cols <= MaxCols { if p.TermSize.Cols > 0 && p.TermSize.Cols <= MaxCols {
cols = p.Cols cols = p.TermSize.Cols
} }
return &pty.Winsize{Rows: uint16(rows), Cols: uint16(cols)} return &pty.Winsize{Rows: uint16(rows), Cols: uint16(cols)}
} }