paramiko执行nohup无效果

paramiko执行nohup无效,后台进程是起来的,但是没数据生成

img

但是,我手动执行nohup命令就没问题

img


#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2023/2/7 17:29
# @Author : LinQ
import sys
import time

import paramiko

from Common.logger.logger import Log

log = Log().logger


class sshClient(object):
    def __init__(self, port, hostname, username, password):
        # 1 创建ssh_client实例
        self.ssh_client = paramiko.SSHClient()
        # 自动处理第一次连接的yes或者no的问题
        self.ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy)
        self.port = port
        self.hostname = hostname
        self.username = username
        self.password = password
        self.ssh_client.connect(
            port=self.port,
            hostname=self.hostname,
            username=self.username,
            password=self.password
        )

    def exec_command(self, shell_command):
        stdin, stdout, stderr = self.ssh_client.exec_command(shell_command)
        log.info("shell_command:%s", shell_command)
        stdout_info = stdout.read().decode('utf-8')
        log.info("stdout_info:%s", stdout_info)
        stderr_info = stderr.read().decode('utf-8')
        log.info("stderr_info:%s", stderr_info)

    def exec_commands(self, shell_commands):
        for shell_command in shell_commands:
            self.exec_command(shell_command)

    def invoke_shell(self, shell_command):
        channel = self.ssh_client.invoke_shell()
        channel.send(shell_command)
        time.sleep(3)
        # stdin, stdout, stderr = self.ssh_client.exec_command(shell_command)
        # log.info("shell_command:%s", shell_command)
        # stdout_info = stdout.read().decode('utf-8')
        # log.info("stdout_info:%s", stdout_info)
        # stderr_info = stderr.read().decode('utf-8')
        # log.info("stderr_info:%s", stderr_info)


if __name__ == '__main__':
    sshclient = sshClient("22", "10.21.16.45", "root", "asiainfo123")
    sshclient.exec_command(". ./.bash_profile ; nohup sh /home/datacollection_sdp/getCPU.sh  >xx.log & ")
    sshclient.exec_command("cd /home/datacollection_sdp;ll ")

shell脚本内容

#!/bin/bash
while true
do
    sar -r 1 1  | tail -1 | awk '{print systime(),$2,$3,$4,$5,$6,$7,$8,$9,$10,$11 }'>>cpu.txt
        sleep 1

done

根据您提供的代码和信息,可能是以下原因导致问题:

1.nohup命令执行后,标准输出和标准错误输出不会立即刷新到文件,而是在进程退出后才会刷新,这可能会导致进程已经启动,但是日志文件还没有被创建或写入。
解决方法:您可以在nohup命令执行后,加一个sleep命令等待一段时间,让进程有足够的时间启动和写入日志文件。例如,将sshclient.exec_command(". ./.bash_profile ; nohup sh /home/datacollection_sdp/xx.sh >xx.log & ")改为sshclient.exec_command(". ./.bash_profile ; nohup sh /home/datacollection_sdp/xx.sh >xx.log & sleep 5")。

2.您的脚本命令中使用了相对路径./.bash_profile,可能导致无法正确加载.bash_profile文件中的环境变量。如果.bash_profile文件不在当前目录下,那么需要指定完整路径。
解决方法:您可以将.bash_profile文件的路径改为绝对路径,例如/root/.bash_profile。

3.您的脚本命令中使用了相对路径./xx.sh,可能导致无法正确找到xx.sh文件。如果xx.sh文件不在当前目录下,那么需要指定完整路径。
解决方法:您可以将xx.sh文件的路径改为绝对路径,例如/home/datacollection_sdp/xx.sh。

4.您的脚本命令没有指定工作目录,可能导致无法正确找到cpu.txt文件的路径。如果cpu.txt文件不在当前目录下,那么需要指定完整路径。
解决方法:您可以在xx.sh脚本中加上cd命令,将工作目录切换到cpu.txt所在的目录,例如:

#!/bin/bash
cd /home/datacollection_sdp/
while true
do
    sar -r 1 1  | tail -1 | awk '{print systime(),$2,$3,$4,$5,$6,$7,$8,$9,$10,$11 }'>>cpu.txt
    sleep 1
done

希望这些解决方法能够帮助您解决问题。

hostname = '192.168.1.1'
username = 'root'
password = '123456'
port = 22

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=hostname, port=port, username=username, password=password)

stdin, stdout, stderr = ssh.exec_command('nohup python3 /root/test.py &')

ssh.close()

以下答案基于ChatGPT与GISer Liu编写:
① 您好,从您的描述中,我猜测您的问题是:使用 Paramiko 执行的 nohup 命令可以在目标主机上启动进程,但无法将生成的数据写入文件中。

根据您提供的代码,我发现在执行 nohup 命令时,使用了 > 符号来重定向输出到文件中。这个符号是 Bash 的语法,而在 exec_command 中执行的命令是在 SSH 服务器上以非交互式的方式运行的,因此没有像终端一样使用 Bash 解释器来解释命令。这意味着,尝试使用 Bash 特定的符号(如 >)可能会失败。

  • 解决方法是,将 nohup 命令与 sh 命令一起使用,让 Bash 解释器来解释命令,如下所示:
    sshclient.exec_command(". ./.bash_profile ; nohup bash -c 'sh /home/datacollection_sdp/xx.sh >xx.log' & ")
    
    这样可以确保在目标主机上使用 Bash 解释器解释命令,并正确地将输出重定向到文件中。

② 另外,您在 invoke_shell 方法中使用了 channel.send(shell_command) 来发送命令,但没有读取服务器的响应。如果您想在交互式模式下执行命令并读取服务器响应,可以使用 Paramiko 的 Channel 对象的 recv 和 send 方法。如果您需要使用非交互式模式,则可以忽略 invoke_shell 方法,并继续使用 exec_command 方法。

希望这些信息可以帮助您解决问题。

参考GPT和自己的思路,根据你提供的代码和信息,初步判断可能的原因是 nohup 命令在后台运行了,但是进程没有正常执行,因此没有生成数据。这可能是因为 nohup 命令的执行路径不对,无法找到 xx.sh 脚本文件。

建议可以尝试在执行 nohup 命令时,指定 xx.sh 的绝对路径来解决该问题。例如:

sshclient.exec_command(". ./.bash_profile ; nohup sh /home/datacollection_sdp/xx.sh > /home/datacollection_sdp/xx.log 2>&1 &")

注意,这里将标准错误输出重定向到了标准输出,以便能够查看执行过程中可能出现的错误信息。

另外,还可以通过在 xx.sh 脚本文件中加入调试信息,查看执行时是否存在错误。例如,可以在脚本中添加如下语句:

echo "Script is running at: $(date)" >> /home/datacollection_sdp/xx.log

这样在脚本执行时,就能够输出调试信息到日志文件中。如果没有日志输出,那么就说明脚本没有正常执行。