通过os.system推送

Tho*_*ood 18 python cron centos

我正在使用crontab为我的minecraft服务器运行维护脚本.大多数情况下它工作正常,除非crontab尝试使用重启脚本.如果我手动运行重启脚本,则没有任何问题.因为我认为它与路径名称有关,所以我试图确保它总是从Minecraft目录中执行任何minecraft命令.所以我在pushd/popd中包含命令:

os.system("pushd /directory/path/here")
os.system("command to sent to minecraft")
os.system("popd")
Run Code Online (Sandbox Code Playgroud)

下面是一个互动会话,将我的世界排除在外.一个简单的"ls"测试.正如你所看到的,它根本没有运行来自pushd目录的os.system命令,而是来自/ etc /,这是我运行python的目录,以说明我的观点.Clearly pushd无法通过python运行所以我想知道我还能做到这一点.谢谢!

>>> def test():
...     import os
...     os.system("pushd /home/[path_goes_here]/minecraft")
...     os.system("ls")
...     os.system("popd")
... 
>>> test()
~/minecraft /etc
DIR_COLORS    cron.weekly  gcrypt         inputrc    localtime   mime.types         ntp       ppp         rc3.d       sasldb2         smrsh      vsftpd.ftpusers
DIR_COLORS.xterm  crontab      gpm-root.conf      iproute2   login.defs  mke2fs.conf            ntp.conf      printcap        rc4.d       screenrc        snmp       vsftpd.tpsave
X11       csh.cshrc    group          issue      logrotate.conf  modprobe.d         odbc.ini      profile         rc5.d       scsi_id.config  squirrelmail   vz
adjtime       csh.login    group-         issue.net  logrotate.d     motd               odbcinst.ini  profile.d       rc6.d       securetty       ssh        warnquota.conf
aliases       cyrus.conf   host.conf      java       lvm         mtab               openldap      protocols       redhat-release  security        stunnel        webalizer.conf
alsa          dbus-1       hosts          jvm        lynx-site.cfg   multipath.conf         opt       quotagrpadmins  resolv.conf     selinux         sudoers        wgetrc
alternatives      default      hosts.allow    jvm-commmon    lynx.cfg    my.cnf             pam.d         quotatab        rndc.key        sensors.conf    sysconfig      xinetd.conf
bashrc        depmod.d     hosts.deny     jwhois.conf    mail        named.caching-nameserver.conf  passwd        rc          rpc         services        sysctl.conf    xinetd.d
blkid         dev.d        httpd          krb5.conf  mail.rc     named.conf         passwd-       rc.d        rpm         sestatus.conf   termcap        yum
cron.d        environment  imapd.conf     ld.so.cache    mailcap     named.rfc1912.zones        pear.conf     rc.local        rsyslog.conf    setuptool.d     udev       yum.conf
cron.daily    exports      imapd.conf.tpsave  ld.so.conf     mailman     netplug            php.d         rc.sysinit      rwtab       shadow          updatedb.conf  yum.repos.d
cron.deny     filesystems  init.d         ld.so.conf.d   makedev.d   netplug.d          php.ini       rc0.d       rwtab.d         shadow-         vimrc
cron.hourly   fonts        initlog.conf   libaudit.conf  man.config  nscd.conf          pki       rc1.d       samba       shells          virc
cron.monthly      fstab        inittab        libuser.conf   maven       nsswitch.conf          postfix       rc2.d       sasl2       skel        vsftpd
sh: line 0: popd: directory stack empty
Run Code Online (Sandbox Code Playgroud)

===(带有python 2.4的CentOS服务器)

小智 77

在Python 2.5及更高版本中,我认为更好的方法是使用上下文管理器,如下所示:

import contextlib
import os


@contextlib.contextmanager
def pushd(new_dir):
    previous_dir = os.getcwd()
    os.chdir(new_dir)
    yield
    os.chdir(previous_dir)
Run Code Online (Sandbox Code Playgroud)

然后,您可以像下面这样使用它:

with pushd('somewhere'):
    print os.getcwd() # "somewhere"

print os.getcwd() # "wherever you started"
Run Code Online (Sandbox Code Playgroud)

通过使用上下文管理器,您将是异常并返回值安全:即使您抛出异常或从上下文块中返回,您的代码也将始终回到它开始的位置.

您还可以在嵌套块中嵌套pushd调用,而不必依赖于全局目录堆栈:

with pushd('somewhere'):
    # do something
    with pushd('another/place'):
        # do something else
    # do something back in "somewhere"
Run Code Online (Sandbox Code Playgroud)

  • 那是我一直在寻找的.但是,如果在with语句中引发异常,则此代码不会弹出,因为@contextmanager不处理异常https://docs.python.org/2/library/contextlib.html您需要使用尝试......终于 (4认同)
  • 我喜欢这个想法,更优雅和pythonic :) (2认同)
  • @MaximeViargues还有一个contextlib`closing`方法,该方法负责try ... finally对您的最终要求https://docs.python.org/2/library/contextlib.html#contextlib.closing (2认同)
  • 只是名字没有选好,恕我直言;因为你没有像 sh 脚本那样的 push/pop 对称,因为 popd 是隐式的 (2认同)

Jos*_*Lee 13

每个shell命令都在一个单独的进程中运行.它生成一个shell,执行pushd命令,然后shell退出.

只需在同一个shell脚本中编写命令:

os.system("cd /directory/path/here; run the commands")
Run Code Online (Sandbox Code Playgroud)

一个更好的(也许)方式是subprocess模块:

from subprocess import Popen
Popen("run the commands", shell=True, cwd="/directory/path/here")
Run Code Online (Sandbox Code Playgroud)


nau*_*101 8

pushd并且popd有一些附加功能:它们将以前的工作目录存储在堆栈中 - 换句话说,您可以pushd五次,做一些事情,popd五次以结束您开始的地方。您在这里没有使用它,但对于其他搜索此类问题的人来说可能会很有用。您可以通过以下方式进行模拟:

# initialise a directory stack
pushstack = list()

def pushdir(dirname):
  global pushstack
  pushstack.append(os.getcwd())
  os.chdir(dirname)

def popdir():
  global pushstack
  os.chdir(pushstack.pop())
Run Code Online (Sandbox Code Playgroud)