2009-04-17 10 views
21

मैं पाइथन के paramiko मॉड्यूल का उपयोग कर एक दूरस्थ मशीन पर tail -f logfile कमांड चलाने के लिए चाहता हूँ। मैं इसे निम्नलिखित फैशन में अब तक के प्रयास में किया गया है:पाइथन paramiko मॉड्यूल में लंबे समय से चल रहे एसएसएच कमांड (और उन्हें कैसे समाप्त करें)

interface = paramiko.SSHClient() 
#snip the connection setup portion 
stdin, stdout, stderr = interface.exec_command("tail -f logfile") 
#snip into threaded loop 
print stdout.readline() 

मैं जब तक आवश्यक चलाने के लिए आदेश चाहते हैं, लेकिन मैं 2 समस्या है:

  1. मैं यह कैसे रोक सकता हूं सफाई से? मैंने चैनल बनाने और चैनल पर shutdown() कमांड का उपयोग करने के बारे में सोचा था जब मैं इसके माध्यम से हूं- लेकिन यह गन्दा लगता है। क्या चैनल के stdin पर Ctrl-C भेजा गया कुछ ऐसा करना संभव है?
  2. readline() ब्लॉक, और अगर मैं आउटपुट प्राप्त करने की गैर-अवरुद्ध विधि था तो मैं थ्रेड से बच सकता था- कोई विचार?
+0

नफरत बुरी खबर को तोड़ने के लिए है, लेकिन SSHClient() पहले से ही आंतरिक रूप से धागे का उपयोग करता है। – joeforker

उत्तर

14

1) यदि आप चाहें तो ग्राहक को बंद कर सकते हैं। दूसरी तरफ सर्वर पूंछ की प्रक्रिया को मार देगा।

2) यदि आपको इसे गैर-अवरुद्ध तरीके से करने की आवश्यकता है, तो आपको सीधे चैनल ऑब्जेक्ट का उपयोग करना होगा। फिर आप stdout और stderr दोनों के लिए channel.recv_ready() और channel.recv_stderr_ready() के साथ देख सकते हैं, या select.select का उपयोग कर सकते हैं।

+1

मुझे पार्टी के लिए देर हो चुकी है, लेकिन 'exec_command' स्वयं गैर-अवरुद्ध नहीं है? – zengr

+1

आप सही हैं, लेकिन सवाल 'readline() 'के बारे में पूछता है। – Dan

+1

कुछ नए सर्वरों पर, आपके क्लाइंट को समाप्त करने के बाद भी आपकी प्रक्रियाएं नहीं मारे जाएंगी। क्लाइंट से बाहर निकलने के बाद प्रक्रियाओं को साफ करने के लिए आपको 'exec_command()' में 'get_pty = True' सेट करना होगा। – nlsun

0

बंद करने के लिए प्रक्रिया बस चलाने:

interface.close() 

nonblocking के संदर्भ में, यदि आप एक nonblocking पढ़ नहीं मिल सकता है। सबसे अच्छा आप इसे एक बार "ब्लॉक" पर पार्स करने में सक्षम होंगे, "stdout.read (1)" केवल तभी अवरुद्ध होगा जब बफर में कोई वर्ण नहीं छोड़ेगा।

21

क्लाइंट पर exec_command को कॉल करने के बजाय, परिवहन को पकड़ें और अपना स्वयं का चैनल बनाएं। channel एक कमांड निष्पादित करने के लिए इस्तेमाल किया जा सकता है, और आप एक का चयन करें बयान में इसका इस्तेमाल करते हैं पता लगाने के लिए कर सकते हैं जब डेटा पढ़ा जा सकता है:

#!/usr/bin/env python 
import paramiko 
import select 
client = paramiko.SSHClient() 
client.load_system_host_keys() 
client.connect('host.example.com') 
transport = client.get_transport() 
channel = transport.open_session() 
channel.exec_command("tail -f /var/log/everything/current") 
while True: 
    rl, wl, xl = select.select([channel],[],[],0.0) 
    if len(rl) > 0: 
     # Must be stdout 
     print channel.recv(1024) 

चैनल वस्तु से पढ़ा जा सकता है और करने के लिए लिखा है, stdout के साथ जोड़ने और रिमोट कमांड का stdin। आप channel.makefile_stderr(...) पर कॉल करके stderr पर जा सकते हैं।

मैंने टाइमआउट को 0.0 सेकंड पर सेट कर दिया है क्योंकि एक गैर-अवरोध समाधान का अनुरोध किया गया था। आपकी जरूरतों के आधार पर, आप गैर-शून्य टाइमआउट के साथ अवरुद्ध करना चाहेंगे।

+0

आप stdout ऑब्जेक्ट पर नहीं चुन सकते हैं, क्योंकि इसमें एक fileno विशेषता नहीं है। goathens एक चैनल वस्तु का उपयोग नहीं कर रहा है। – JimB

+0

मैंने उदाहरण को संशोधित और विस्तारित किया है, और यह सुनिश्चित करने के लिए इसका परीक्षण किया है कि यह काम करता है :)। –

+0

क्या यह एसएलडीआर के साथ काम करता है अगर आप एक्सएल द्वारा आरएल को प्रतिस्थापित करते हैं? –

0

बस जानकारी के लिए, channel.get_pty() का उपयोग करके ऐसा करने का एक समाधान है। अधिक जानकारी के लिए एक नज़र डालें: https://stackoverflow.com/a/11190727/1480181

6

एंड्रयू अयलेट द्वारा समाधान के लिए बस एक छोटा सा अपडेट। निम्नलिखित कोड वास्तव में पाश टूट जाता है और छोड़ देता है बाहरी प्रक्रिया खत्म:

import paramiko 
import select 

client = paramiko.SSHClient() 
client.load_system_host_keys() 
client.connect('host.example.com') 
channel = client.get_transport().open_session() 
channel.exec_command("tail -f /var/log/everything/current") 
while True: 
    if channel.exit_status_ready(): 
     break 
    rl, wl, xl = select.select([channel], [], [], 0.0) 
    if len(rl) > 0: 
     print channel.recv(1024) 
+2

क्यों न करें 'channel.exit_status_ready(): '? – azmeuk

+0

इसके अलावा, http://stackoverflow.com/questions/760978/long-running-ssh-commands-in-python-paramiko- मॉड्यूल- और-how-to-end-them#comment64123397_766255 – azmeuk

+1

@azmeuk दोनों समाधान थोड़ा हैं गलत, क्योंकि जैसे ही बाहर निकलने की स्थिति तैयार हो जाती है, आप आउटपुट प्राप्त करना बंद नहीं करना चाहते हैं। जब आप कोई आउटपुट प्राप्त नहीं करते हैं और बाहर निकलने की स्थिति तैयार होती है तो आप रुकना चाहते हैं। अन्यथा आप सभी आउटपुट प्राप्त करने से पहले छोड़ने को समाप्त कर सकते हैं। – user7610

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

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