paramiko执行nohup无效,后台进程是起来的,但是没数据生成
但是,我手动执行nohup命令就没问题
#!/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 特定的符号(如 >)可能会失败。
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
这样在脚本执行时,就能够输出调试信息到日志文件中。如果没有日志输出,那么就说明脚本没有正常执行。