Python和shell中的多线程

Python和shell中的多线程,python,multithreading,Python,Multithreading,我有一个名为“nn.sh”的shell脚本,它将本地网络中的一个ip地址和SSH连接到该ip,然后从该ip连续读取一些数据,并将结果附加到服务器上名为“log.txt”的文件中 我需要编写一个Python代码在服务器上运行,该服务器可能使用多线程在一个线程中运行该脚本,然后在另一个线程中读取文件“log.txt”中已有的值。我该怎么做 我编写了以下代码: #!/usr/bin/python import threading import time from subprocess import c

我有一个名为“nn.sh”的shell脚本,它将本地网络中的一个ip地址和SSH连接到该ip,然后从该ip连续读取一些数据,并将结果附加到服务器上名为“log.txt”的文件中

我需要编写一个Python代码在服务器上运行,该服务器可能使用多线程在一个线程中运行该脚本,然后在另一个线程中读取文件“log.txt”中已有的值。我该怎么做

我编写了以下代码:

#!/usr/bin/python
import threading
import time
from subprocess import call, Popen, PIPE

exitFlag = 0

class loggerThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        print "Logging thread started ..."
    def run(self):
        with open("log.txt","at") as log: 
                call(['/bin/sh', 'nn.sh', '172.20.125.44', '10'], stdout = log)

class readerThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        print "Reading thread started ..."
    def run(self):
        while 1:
                with open("log.txt","r") as log:
                        lines = log.read().split("\n")
                        print "Reader thread  ..."
                        print lines[-1]


thread1 = loggerThread()
thread2 = readerThread()

thread1.start()
thread2.start()
以下是“nn.sh”的内容:


ssh-o IdentityFile=~/Dropbox/ALI/id\u rsa-l root$1试图通过这样的文件将信息从一个进程(或线程)流式传输到另一个进程(或线程)是个坏主意。您必须让编写器确保在每行之后刷新文件(并且不要在行中间刷新文件),您必须进行同步,以便只在有新数据要读取时读取文件,而不是尽可能快地旋转,您必须弄清楚如何检测何时有新数据要读取(这是特定于平台的),等等

这正是管道的用途。事实上,考虑到这一点:

from subprocess import call, Popen, PIPE
…我怀疑您是从一些使用管道进行操作的代码中复制和粘贴的,否则,您为什么要导入
管道

还有,我不知道你为什么认为这里需要两个线程。如果必须向shell脚本发送输入并读取输出,那么使用两个线程可能会更容易。但您所要做的只是启动一个子进程,并在其可用时读取其输出。所以只要从主线程的管道中读取

文档中有一些示例,说明了如何准确地执行您想要的操作

from subprocess import call, Popen, PIPE
p = Popen(['/bin/sh', 'nn.sh', '172.20.125.44', '10'], stdout=PIPE)
for line in p.stdout:
    print line
p.wait()
在管道上迭代将阻塞,直到另一行可用,然后读取整行,只要没有一行的长度超过
select.pipe\u BUF
(保证至少为512)


如果出于其他原因需要将其放入线程中(例如,需要在主线程中执行一些其他工作,而该线程正在收集输出),则可以使用与Python中任何其他线程完全相同的方法:创建
threading.thread
子类,或者传递
target
函数。例如:

def nnsh():
    from subprocess import call, Popen, PIPE
    p = Popen(['/bin/sh', 'nn.sh', '172.20.125.44', '10'], stdout=PIPE)
    for line in p.stdout:
        print line
    p.wait()
t = threading.Thread(target=nnsh)
t.start()
# do a bunch of other stuff
t.join()
(当然,您可以将其设置为守护进程线程,或者想出一种方法来向其发送信号,而不是将其与无限超时连接起来,等等;如果您知道自己想要什么但不知道如何做,请阅读基本教程或
线程
模块文档,如果您被困在某个地方,请发布一个单独的新问题。)


如果在某些*nix平台上(尽管在最新版本的OS X、FreeBSD、Linux或Solaris上似乎没有必要),您可能需要手动循环,而不是:

buf = ''
while True:
    buf += p.stdout.read(select.PIPE_BUF)
    lines = buf.split('\n')
    for line in lines[:-1]:
        print line
    buf = lines[-1]

试图通过这样的文件将信息从一个进程(或线程)流到另一个进程(或线程)是一个坏主意。您必须让编写器确保在每行之后刷新文件(并且不要在行中间刷新文件),您必须进行同步,以便只在有新数据要读取时读取文件,而不是尽可能快地旋转,您必须弄清楚如何检测何时有新数据要读取(这是特定于平台的),等等

这正是管道的用途。事实上,考虑到这一点:

from subprocess import call, Popen, PIPE
…我怀疑您是从一些使用管道进行操作的代码中复制和粘贴的,否则,您为什么要导入
管道

还有,我不知道你为什么认为这里需要两个线程。如果必须向shell脚本发送输入并读取输出,那么使用两个线程可能会更容易。但您所要做的只是启动一个子进程,并在其可用时读取其输出。所以只要从主线程的管道中读取

文档中有一些示例,说明了如何准确地执行您想要的操作

from subprocess import call, Popen, PIPE
p = Popen(['/bin/sh', 'nn.sh', '172.20.125.44', '10'], stdout=PIPE)
for line in p.stdout:
    print line
p.wait()
在管道上迭代将阻塞,直到另一行可用,然后读取整行,只要没有一行的长度超过
select.pipe\u BUF
(保证至少为512)


如果出于其他原因需要将其放入线程中(例如,需要在主线程中执行一些其他工作,而该线程正在收集输出),则可以使用与Python中任何其他线程完全相同的方法:创建
threading.thread
子类,或者传递
target
函数。例如:

def nnsh():
    from subprocess import call, Popen, PIPE
    p = Popen(['/bin/sh', 'nn.sh', '172.20.125.44', '10'], stdout=PIPE)
    for line in p.stdout:
        print line
    p.wait()
t = threading.Thread(target=nnsh)
t.start()
# do a bunch of other stuff
t.join()
(当然,您可以将其设置为守护进程线程,或者想出一种方法来向其发送信号,而不是将其与无限超时连接起来,等等;如果您知道自己想要什么但不知道如何做,请阅读基本教程或
线程
模块文档,如果您被困在某个地方,请发布一个单独的新问题。)


如果在某些*nix平台上(尽管在最新版本的OS X、FreeBSD、Linux或Solaris上似乎没有必要),您可能需要手动循环,而不是:

buf = ''
while True:
    buf += p.stdout.read(select.PIPE_BUF)
    lines = buf.split('\n')
    for line in lines[:-1]:
        print line
    buf = lines[-1]

该进程不必从Python而是从shell进行多线程处理。将shell脚本放在一个函数中,并通过附加一个符号(&)来调用它,以便在另一个进程中调用它。你可以通过找到PID来杀死它。然后迭代日志文件,并在写入文件时打印任何内容。

该过程不必从Python而是从shell进行多线程处理。将shell脚本放在一个函数中,并通过附加一个符号(&)来调用它,以便在另一个进程中调用它。你可以通过找到PID来杀死它。然后迭代日志文件,并在写入文件时打印任何内容。

这是@abarnert概念的一个变体。它在子流程中运行“nn.sh”命令,然后处理显示的每一行数据。输出被写入sys.stdout,然后刷新,这样我们就可以看到它的出现,而不是最后的全部

来源
这是@abarnert概念的变体。它运行于