我正在尝试获取在远程服务器中使用 ssh 会话执行的命令的 pid。但 pid 为空。有这方面的帮助吗?
这是我的程序..
func (c *SSHClient) RunCommandWithContext(ctx context.Context, command string) (string, error) {
if c.Client == nil {
return "", errors.New("SSH client is not connected")
}
session, err := c.Client.NewSession()
if err != nil {
return "", err
}
defer session.Close()
var stdoutBuf bytes.Buffer
session.Stdout = &stdoutBuf
// Channel to signal completion
done := make(chan error, 1)
// Run the command and get the PID
var stdout, stderr bytes.Buffer
session.Stdout = &stdout
session.Stderr = &stderr
go func() {
done <- session.Run(command)
}()
// Extract the PID from the output
output := strings.TrimSpace(stdout.String())
fmt.Println("Output:", output) <-- this is coming empty
pid, err := strconv.Atoi(output)
fmt.Println("PID:", pid) <--- I need the pid of the command I am executing remoting.
fmt.Println("Error:", err)
if err != nil {
log.Fatalf("Failed to parse PID: %v", err)
}
log.Printf("Started command with PID %d\n", pid)
ticker := time.NewTicker(2 * time.Second)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
// Context timeout
if err := session.Signal(ssh.SIGKILL); err != nil {
return "", fmt.Errorf("failed to kill process: %w", err)
}
return "", ctx.Err()
case <-ticker.C:
log.Println("Checking command status...")
if !isProcessRunning(session, pid) {
log.Println("Command finished successfully")
printLogs(stdout.String(), stderr.String())
return "", nil
}
case err := <-done:
// Command completed
if err != nil {
return "", err
}
return stdoutBuf.String(), nil
}
}
return "", nil
}
// This program asynchronously checks if the command has completed or not
func isProcessRunning(session *ssh.Session, pid int) bool {
command := fmt.Sprintf("ps -p %d", pid)
if err := session.Run(command); err != nil {
return false
}
// Run the command and get the PID
var stdout, stderr bytes.Buffer
session.Stdout = &stdout
session.Stderr = &stderr
output := strings.TrimSpace(stdout.String())
return strings.Contains(output, strconv.Itoa(pid))
}
实际上,在 pid 的帮助下,我需要检查命令是否已成功完成或以某种失败状态退出。请让我知道如何使用会话本身来实现这一点
我不确定你打算如何从 PID 进入其退出状态。 但无论如何也没有必要这样做! ssh.Session 本身支持这一点。
如果命令不成功,ssh.Session.Run会返回错误:
如果命令运行,复制 stdin、stdout 和 stderr 没有问题,并且以零退出状态退出,则返回的错误为零。
如果远程服务器未发送退出状态,则返回 *ExitMissingError 类型的错误。如果命令未成功完成或被信号中断,则错误类型为 *ExitError。 I/O 问题可能会返回其他错误类型。
如果您从
Run()
收到错误,您可以执行类型断言或 errors.As
来查看它是否是 *ssh.ExitError
。 如果是,您就知道该命令失败并可以根据需要进行处理。
*ssh.ExitError
,您可以根据需要确定退出代码。 更有用的是在任何错误消息中包含 stderr 缓冲区,因为它将包含命令可能提供的有关失败原因的任何解释。
然后您可以删除股票代码和
ps
逻辑等等。 在任何语言中,您都不需要轮询来查看子流程是否已结束;总有办法等待。