Python 脚本手动成功但在 crontab 上失败

tpa*_*ott 4 python cron

所以我目前正在尝试让脚本工作,但是当我手动运行它时它的行为与我从 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 user@192.168.100.10', 'testGet':'wget http://192.168.100.11/test.html -t 1 -T 10', 'tunnel':'start_tunnel'}, {address':'192.168.100.12', 'connString':'ssh user@192.168.100.12', '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()
Run Code Online (Sandbox Code Playgroud)

我的 crontab 条目如下:

0,30 * * * * python /home/user/tunnelTest.py
Run Code Online (Sandbox Code Playgroud)

所以是的 - 这个脚本在我手动执行时运行良好(sudo python tunnelTest.py)并且在 crontab 上也运行良好,除非隧道关闭。当隧道关闭时,我会听到“隧道关闭!” 和“从远程主机 192.168.100.10 断开连接并重新启动隧道”消息在我的日志中,但脚本似乎死在那里。隧道不会重新启动,并且在下一次计划运行开始之前,我的日志中没有任何消息。

start_tunnel 脚本在 /etc/init 中,testTunnel.py 脚本在 /home/user 中,testTunnel.log 文件在 /home/user/logs 中,我以 root 身份运行 crontab -e。

对此事的任何见解将不胜感激。

谢谢!

小智 5

您需要使用python的完整路径,例如

/usr/bin/python

你可以找到路径 which python

所以你的 crontab 条目看起来像

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

  • 您必须牢记 cronjobs 看到的环境变量与交互式提示不同。 (2认同)