2011-10-06 9 views
9

हमारे पास कई एप्लिकेशन सर्वर हैं, और एक केंद्रीय निगरानी सर्वर है।पाइथन रिमोट पूंछ अनुकरण करने के लिए?

हम वर्तमान में ऐप सर्वर से रीयलटाइम में कई टेक्स्ट लॉगफाइल स्ट्रीम करने के लिए निगरानी सर्वर से "tail -f" के साथ ssh चला रहे हैं।

मुद्दा, पूरे दृष्टिकोण की बेरहमी के अलावा यह मुद्दा है कि एसएसएच प्रक्रिया को मारने से कभी-कभी ज़ोंबी पूंछ की प्रक्रियाओं को पीछे छोड़ दिया जा सकता है। हमने छद्म टर्मिनलों को बनाने के लिए उपयोग करने के साथ चारों ओर उलझा लिया है, लेकिन यह कभी-कभी ज़ोंबी प्रक्रियाओं को छोड़ देता है, और यह स्पष्ट रूप से नौकरी शेड्यूलिंग उत्पाद के साथ कहीं और समस्याएं पैदा कर रहा है।

एक सस्ता और गंदे समाधान के रूप में जब तक हम उचित केंद्रीकृत लॉगिंग (लॉगस्टैश और खरगोश एमक्यू, उम्मीदपूर्वक) प्राप्त नहीं कर सकते, मैं एक साधारण पायथन रैपर लिखने की उम्मीद कर रहा हूं जो एसएसएच और "पूंछ-एफ" शुरू करेगा, अभी भी कैप्चर करेगा आउटपुट, लेकिन पीआईडी ​​को डिस्क पर टेक्स्टफाइल पर स्टोर करें ताकि आवश्यकता होने पर बाद में उचित पूंछ प्रक्रिया को मार सकें।

मैंने पहली बार subprocess.Popen का उपयोग करने की कोशिश की, लेकिन फिर मैंने रीयलटाइम में "tail -f" आउटपुट वापस प्राप्त करने के साथ मुद्दों को मारा (जिसे तब फ़ाइल में रीडायरेक्ट करने की आवश्यकता होती है) - जाहिर है कि वहां होने जा रहे हैं ब्लॉकिंग/बफर मुद्दों का मेजबान।

कुछ स्रोत pexpect, या pxssh या ऐसा कुछ उपयोग करने की अनुशंसा करते थे। आदर्श रूप से मैं केवल पायथन का उपयोग करना चाहता हूं और यदि संभव हो तो इसमें पुस्तकालय शामिल हैं - हालांकि, यदि पुस्तकालय वास्तव में ऐसा करने का एकमात्र तरीका है, तो मैं इसके लिए खुला हूं।

क्या "पूंछ-एफ" के साथ एसएसएच शुरू करने के लिए पाइथन प्राप्त करने का एक अच्छा आसान तरीका है, यहां स्थानीय STDOUT पर रीयलटाइम में आउटपुट प्राप्त करें (इसलिए मैं स्थानीय फ़ाइल पर रीडायरेक्ट कर सकता हूं), और पीआईडी ​​को भी सहेज रहा हूं बाद में मारने के लिए एक फाइल के लिए? या यहां तक ​​कि अगर मैं पूंछ-एफ के साथ एसएसएच का उपयोग नहीं करता हूं, फिर भी रीयलटाइम में एक दूरस्थ फ़ाइल स्ट्रीम करने का कोई तरीका है जिसमें पीआईडी ​​को फाइल में सहेजना शामिल है?

चीयर्स, विक्टर

संपादित करें: बस स्पष्ट करने के लिए - हम पूंछ प्रक्रिया मरना चाहते जब हम SSH प्रक्रिया मार डालते हैं।

हम निगरानी सर्वर से ssh और "पूंछ -f" शुरू करने के लिए है, तो जब हम Ctlr-सी है कि दूरदराज के बॉक्स पर पूंछ प्रक्रिया के रूप में अच्छी तरह से मौत हो जाए चाहते हैं - हम यह रहने के लिए नहीं चाहते हैं पीछे। आम तौर पर एसएसएच को इसे ठीक करना चाहिए, लेकिन यह पूरी तरह से विश्वसनीय नहीं है, जिन कारणों से मुझे समझ में नहीं आता है, और यह हमारे नौकरी शेड्यूलिंग के साथ अच्छी तरह से खेल नहीं आता है।

इसलिए, दूसरी तरफ प्रक्रिया को जीवित रखने के लिए स्क्रीन का उपयोग करना हम नहीं चाहते हैं।

+0

यह भी देखें http://stackoverflow.com/questions/136168/get-last-n-lines-of-a-file-with-python-similar-to-tail – unmounted

+0

@bmvou, प्रश्न 'tail -f' –

+0

के बारे में कुछ भी नहीं है शायद http://stackoverflow.com/questions/1703640/how-to-implement-a-pythonic-equivalent-of-tail-f? – agf

उत्तर

0

पैरामीको मॉड्यूल पाइथन के साथ एसएसएच के माध्यम से कनेक्ट करने का समर्थन करता है।

http://www.lag.net/paramiko/

pysftp यह और निष्पादित आदेश विधि का उपयोग हो सकता है आपके लिए क्या देख के कुछ उदाहरण हैं। यह आपके द्वारा निष्पादित आदेश के ऑब्जेक्ट की तरह एक फ़ाइल बनाएगा। मैं यह नहीं कह सकता कि यह आपको लाइव डेटा देता है या नहीं।

http://code.google.com/p/pysftp/

6

मैं जानता हूँ कि यह आपके सवालों के जवाब नहीं है, लेकिन ...

हो सकता है कि आप स्क्रीन का उपयोग कर की कोशिश कर सकते। यदि आपका सत्र गिरता है, तो आप हमेशा पुनः जोड़ सकते हैं और पूंछ अभी भी चल रही है। यह बहुउद्देशीय का भी समर्थन करता है, इसलिए 2 उपयोगकर्ता एक ही पूंछ कमांड देख सकते हैं।

http://en.wikipedia.org/wiki/GNU_Screen

नाम के साथ बनाने के "लॉग ऑन":

screen -S log 

डिस्कनेक्ट:

[CTRL]+A D 

जब आप याद कर सकते हैं पुनः अनुलग्न

screen -r log 

सूची नाम

screen -list 

, सत्र से छुटकारा पाने के लिए बस टाइप उस में exit है।

+5

+1 के लिए fcntl, अस्वीकार, मतदान या शेष के कुछ भी कुछ भी चाहिए। –

+0

स्क्रीन और कपड़े के लिए सही टूल का उपयोग करने के लिए – Tom

2

मुझे लगता है कि स्क्रीन विचार सबसे अच्छा विचार है, लेकिन यदि आप एसएसएच नहीं चाहते हैं और आप इसे एक पाइथन स्क्रिप्ट करना चाहते हैं। यहां जानकारी प्राप्त करने का एक सरल पायथनिक एक्सएमएलआरपीसी तरीका है। यह केवल तभी अपडेट होगा जब फ़ाइल में कुछ जोड़ा गया हो।

यह ग्राहक फ़ाइल है। आप यह बताते हैं कि आप किस फाइल को पढ़ना चाहते हैं और किस कंप्यूटर पर।

#!/usr/bin/python 
# This should be run on the computer you want to output the files 
# You must pass a filename and a location 
# filename must be the full path from the root directory, or relative path 
# from the directory the server is running 
# location must be in the form of http://location:port (i.e. http:localhost:8000) 

import xmlrpclib, time, sys, os 

def tail(filename, location): 
    # connect to server 
    s = xmlrpclib.ServerProxy(location) 

    # get starting length of file 
    curSeek = s.GetSize(filename) 

    # constantly check 
    while 1: 
     time.sleep(1) # make sure to sleep 

     # get a new length of file and check for changes 
     prevSeek = curSeek 

     # some times it fails if the file is being writter to, 
     # we'll wait another second for it to finish 
     try: 
     curSeek = s.GetSize(filename) 
     except: 
     pass 

     # if file length has changed print it 
     if prevSeek != curSeek: 
     print s.tail(filename, prevSeek), 


def main(): 
    # check that we got a file passed to us 
    if len(sys.argv) != 3 or not os.path.isfile(sys.argv[1]): 
     print 'Must give a valid filename.' 
     return 

    # run tail function 
    tail(sys.argv[1], sys.argv[2]) 

main() 

यह सर्वर है जिसे आप प्रत्येक कंप्यूटर पर चलाएंगे जिसमें एक फ़ाइल है जिसे आप देखना चाहते हैं। इसकी कोई कल्पना नहीं है। यदि आप चाहें तो आप इसे डिमन कर सकते हैं। आप इसे अभी चलाते हैं, और आप क्लाइंट से कनेक्ट होना चाहिए यदि आप क्लाइंट को बताते हैं कि यह कहां है और आपके पास सही बंदरगाह खुले हैं।

#!/usr/bin/python 
# This runs on the computer(s) you want to read the file from 
# Make sure to change out the HOST and PORT variables 
HOST = 'localhost' 
PORT = 8000 

from SimpleXMLRPCServer import SimpleXMLRPCServer 
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler 

import time, os 

def GetSize(filename): 
    # get file size 
    return os.stat(filename)[6] 

def tail(filename, seek): 
    #Set the filename and open the file 
    f = open(filename,'r') 

    #Find the size of the file and move to the end 
    f.seek(seek) 
    return f.read() 

def CreateServer(): 
    # Create server 
    server = SimpleXMLRPCServer((HOST, PORT), 
           requestHandler=SimpleXMLRPCRequestHandler) 

# register functions 
    server.register_function(tail, 'tail') 
    server.register_function(GetSize, 'GetSize') 

    # Run the server's main loop 
    server.serve_forever() 

# start server 
CreateServer() 

आदर्श रूप में आप सर्वर एक बार तो ग्राहक रन "अजगर client.py sample.log http://somehost:8000" से चलाने के लिए, और यह जा रहा शुरू कर देना चाहिए। उम्मीद है की वो मदद करदे।

0

पर एक प्रश्न पोस्ट किया मैं एक समारोह है कि है कि लिखा है:

import paramiko 
import time 
import json 

DEFAULT_MACHINE_USERNAME="USERNAME" 
DEFAULT_KEY_PATH="DEFAULT_KEY_PATH" 

def ssh_connect(machine, username=DEFAULT_MACHINE_USERNAME, 
       key_filename=DEFAULT_KEY_PATH): 
    ssh = paramiko.SSHClient() 
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 
    ssh.connect(hostname=machine, username=username, key_filename=key_filename) 
    return ssh 

def tail_remote_file(hostname, filepath, key_path=DEFAULT_KEY_PATH, 
        close_env_variable="CLOSE_TAIL_F", env_file='~/.profile'): 
    ssh = ssh_connect(hostname, key_filename=key_path) 

    def set_env_variable(to_value): 
     to_value_str = "true" if to_value else "false" 
     from_value_str = "false" if to_value else "true" 
     ssh.exec_command('sed -i \'s/export %s=%s/export %s=%s/g\' %s' % 
         (close_env_variable, from_value_str, 
          close_env_variable, to_value_str, env_file)) 
     time.sleep(1) 

    def get_env_variable(): 
     command = "source .profile; echo $%s" % close_env_variable 
     stdin, stdout_i, stderr = ssh.exec_command(command) 
     print(command) 
     out = stdout_i.read().replace('\n', '') 
     return out 

    def get_last_line_number(lines_i, line_num): 
     return int(lines_i[-1].split('\t')[0]) + 1 if lines_i else line_num 

    def execute_command(line_num): 
     command = "cat -n %s | tail --lines=+%d" % (filepath, line_num) 
     stdin, stdout_i, stderr = ssh.exec_command(command) 
     stderr = stderr.read() 
     if stderr: 
      print(stderr) 
     return stdout_i.readlines() 

    stdout = get_env_variable() 
    if not stdout: 
     ssh.exec_command("echo 'export %s=false' >> %s" % 
         (close_env_variable, env_file)) 
    else: 
     ssh.exec_command(
      'sed -i \'s/export %s=true/export %s=false/g\' %s' % 
      (close_env_variable, close_env_variable, env_file)) 
    set_env_variable(False) 

    lines = execute_command(0) 
    last_line_num = get_last_line_number(lines, 0) 

    while not json.loads(get_env_variable()): 
     for l in lines: 
      print('\t'.join(t.replace('\n', '') for t in l.split('\t')[1:])) 
     last_line_num = get_last_line_number(lines, last_line_num) 
     lines = execute_command(last_line_num) 
     time.sleep(1) 

    ssh.close() 
0

मैं मैंने एक लाइब्रेरी लिखी है जो आपको ऐसा करने की अनुमति देती है - PimpedSubprocess (गीथब पर) याकी "दूरस्थ" सुविधा देखें(पीईपीआई पर)

संबंधित मुद्दे