feat(ssh): allow running remote commands via ssh

- update ssh command to accept optional remote command argument
- modify sshInto to execute commands non-interactively when provided
- comment out unreachable node in nodes.conf
This commit is contained in:
anonpenguin23 2026-05-03 14:55:43 +03:00
parent 69c7ed5e5a
commit 54852076f9
2 changed files with 22 additions and 9 deletions

View File

@ -16,13 +16,21 @@ var envFlag string
// Cmd is the top-level "ssh" command — SSH into any node by IP or hostname. // Cmd is the top-level "ssh" command — SSH into any node by IP or hostname.
var Cmd = &cobra.Command{ var Cmd = &cobra.Command{
Use: "ssh <ip-or-hostname>", Use: "ssh <ip-or-hostname> [-- command]",
Short: "SSH into a node", Short: "SSH into a node",
Long: `SSH into a node by IP address or hostname. Long: `SSH into a node by IP address or hostname.
Resolves the SSH key from rootwallet automatically.`, Resolves the SSH key from rootwallet automatically.
Args: cobra.ExactArgs(1),
Pass a command after the IP to run it non-interactively:
orama ssh 1.2.3.4 'sudo systemctl status orama-node'`,
Args: cobra.MinimumNArgs(1),
DisableFlagParsing: false,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
target := args[0] target := args[0]
remoteCmd := ""
if len(args) > 1 {
remoteCmd = args[1]
}
env := envFlag env := envFlag
if env == "" { if env == "" {
@ -42,7 +50,7 @@ Resolves the SSH key from rootwallet automatically.`,
// Match by IP // Match by IP
for _, n := range nodes { for _, n := range nodes {
if n.Host == target { if n.Host == target {
return sshInto(n) return sshInto(n, remoteCmd)
} }
} }
@ -52,7 +60,7 @@ Resolves the SSH key from rootwallet automatically.`,
Host: target, Host: target,
User: "root", User: "root",
VaultTarget: target + "/root", VaultTarget: target + "/root",
}) }, remoteCmd)
}, },
} }
@ -60,7 +68,7 @@ func init() {
Cmd.Flags().StringVar(&envFlag, "env", "", "Environment to search (default: active)") Cmd.Flags().StringVar(&envFlag, "env", "", "Environment to search (default: active)")
} }
func sshInto(node inspector.Node) error { func sshInto(node inspector.Node, remoteCmd string) error {
nodes := []inspector.Node{node} nodes := []inspector.Node{node}
cleanup, err := remotessh.PrepareNodeKeys(nodes) cleanup, err := remotessh.PrepareNodeKeys(nodes)
if err != nil { if err != nil {
@ -75,12 +83,17 @@ func sshInto(node inspector.Node) error {
return fmt.Errorf("ssh not found in PATH: %w", err) return fmt.Errorf("ssh not found in PATH: %w", err)
} }
sshCmd := exec.Command(sshBin, sshArgs := []string{
"-i", keyPath, "-i", keyPath,
"-o", "StrictHostKeyChecking=accept-new", "-o", "StrictHostKeyChecking=accept-new",
"-o", "IdentitiesOnly=yes", "-o", "IdentitiesOnly=yes",
fmt.Sprintf("%s@%s", node.User, node.Host), fmt.Sprintf("%s@%s", node.User, node.Host),
) }
if remoteCmd != "" {
sshArgs = append(sshArgs, remoteCmd)
}
sshCmd := exec.Command(sshBin, sshArgs...)
sshCmd.Stdin = os.Stdin sshCmd.Stdin = os.Stdin
sshCmd.Stdout = os.Stdout sshCmd.Stdout = os.Stdout
sshCmd.Stderr = os.Stderr sshCmd.Stderr = os.Stderr

View File

@ -14,7 +14,7 @@ devnet|ubuntu@51.38.128.56|nameserver-ns3
devnet|ubuntu@144.217.162.62|node devnet|ubuntu@144.217.162.62|node
devnet|ubuntu@51.83.128.181|node devnet|ubuntu@51.83.128.181|node
devnet|ubuntu@144.217.160.15|node devnet|ubuntu@144.217.160.15|node
devnet|root@46.250.241.133|node # devnet|root@46.250.241.133|node # TODO: add rootwallet key
devnet|root@109.123.229.231|node devnet|root@109.123.229.231|node
devnet|ubuntu@144.217.162.143|node devnet|ubuntu@144.217.162.143|node
devnet|ubuntu@144.217.163.114|node devnet|ubuntu@144.217.163.114|node