web-dev-qa-db-ja.com

Pythonスクリプトは手動で成功しますが、crontabでは失敗します

そのため、現在スクリプトを機能させようとしていますが、手動で実行した場合とcrontabから実行した場合では動作が異なります。基本的に、あるサーバーから別のサーバーにリバースsshトンネルがセットアップされています。トンネルが稼働していることを確認するために、次のようにします。

  • サーバーAからサーバーBへのSSH
  • サーバーBからサーバーAのテストURLを取得する
  • wgetが成功した場合、切断して何もしません
  • wgetが失敗した場合は、トンネルを切断して再起動します

Sshトンネルを検証するよりエレガントな方法(autosshやServerKeepAliveなど)があることは知っていますが、ポリシーと冗長性の両方の問題では、この方法で行う必要があります。とにかく、これがスクリプトです。

from __future__ import print_function
from __future__ import absolute_import

import os, sys, subprocess, logging, pexpect

COMMAND_Prompt = '[#$] '
TERMINAL_Prompt = '(?1)terminal type\?'
TERMINAL_TYPE = 'vt100'
SSH_NEWKEY = '(?i)are you sure you want to continue connecting'
SERVERS = [{address':'192.168.100.10', 'connString':'ssh [email protected]', 'testGet':'wget http://192.168.100.11/test.html -t 1 -T 10', 'tunnel':'start_tunnel'}, {address':'192.168.100.12', 'connString':'ssh [email protected]', 'testGet':'wget http://192.168.100.13/test.html -t 1 -T 10', 'tunnel':'start_tunnel2'}]

def main():

    global COMMAND_Prompt, TERMINAL_Prompt, TERMINAL_TYPE, SSH_NEWKEY, SERVERS

    #set up logging
    log = logging.getLogger(__name__)
    log.setLevel(logging.DEBUG)
    handler = logging.FileHandler('/home/user/tunnelTest.log')
    formatter = logging.Formatter('%(asctime)s - %(module)s.%(funcName)s: %(message)s')
    handler.setFormatter(formatter)
    log.addHandler(handler)


    for x in SERVERS:

        #connect to server
        child = pexpect.spawn(x['connString'])
        i = child.expect([pexpect.TIMEOUT, SSH_NEWKEY, COMMAND_Prompt, '(?i)password'])
        if i == 0:   #Timeout
             log.debug('ERROR! Could not log in to ' + x['address'] + ' ...')
             sys.exit(1)
        if i = 1:    #No key cached
             child.sendline('yes')
             child.expect(COMMAND_Prompt)
             log.debug('Connected to ' + x['address'] + '...')
        if i = 2:    #Good to go
             log.debug('Connected to ' + x['address'] + '...')
             pass

        #Housecleaning
        child.sendline('cd /tmp')
        child.expect(COMMAND_LINE)
        child.sendline('rm -r test.html')
        child.expect(COMMAND_LINE)

        log.debug('Testing service using ' + x['testGet'] + ' ...')
        child.sendline(x['testGet'])
        child.expect(COMMAND_Prompt)
        if 'saved' in child.before.lower():
            log.debug('Tunnel working, nothing to do here!')
            log.debug('Disconnecting from remote Host ' + x['address'] + '...')
            child.sendline('exit')
        else:
            log.error('Tunnel down!')
            log.debug('Disconnecting from remote Host ' + x['address'] + ' and restarting tunnel')
            child.sendline('exit')
            subprocess.call(['start',x['tunnel']])
            log.debug('Autossh tunnel restarted')

if __name__ == "__main__":
    main()

私のcrontabエントリは次のとおりです。

0,30 * * * * python /home/user/tunnelTest.py

だからそうです-このスクリプトは手動で実行すると正常に実行され(Sudo python tunnelTest.py))、トンネルがダウンしていない限りcrontabでも正常に実行されます。トンネルがダウンすると、 「トンネルダウン!」および「リモートホスト192.168.100.10から切断してトンネルを再起動しています」というメッセージがログに記録されますが、スクリプトがそこで停止したようです。トンネルは再起動せず、ログが開始されるまでメッセージが表示されません次のスケジュールされた実行。

Start_tunnelスクリプトは/ etc/initにあり、testTunnel.pyスクリプトは/ home/userにあり、testTunnel.logファイルは/ home/user/logsにあり、crontab -eをrootとして実行しました。

この問題への洞察は大歓迎です。

ありがとう!

4
tparrott

pythonへのフルパスを使用する必要があります。例:

/usr/bin/python

あなたはwhich pythonでパスを見つけることができます

したがって、crontabエントリは次のようになります。

0,30 * * * * /usr/bin/python /home/user/tunnelTest.py

5
squareborg