Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/365.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 推送通过操作系统_Python_Cron_Centos - Fatal编程技术网

Python 推送通过操作系统

Python 推送通过操作系统,python,cron,centos,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

我正在使用crontab为我的minecraft服务器运行维护脚本。大多数情况下,它工作正常,除非crontab尝试使用重启脚本。如果手动运行重启脚本,则不会出现任何问题。因为我相信这与路径名有关,所以我试图确保它总是从minecraft目录执行任何minecraft命令。所以我将命令封装在pushd/popd中:

os.system("pushd /directory/path/here")
os.system("command to sent to minecraft")
os.system("popd")
下面是一个交互式会话,将minecraft排除在等式之外。一个简单的“ls”测试。正如您所看到的,它根本不从pushd目录运行os.system命令,而是从/etc/运行,我在其中运行python来说明我的观点。显然,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
===
(使用python 2.4的CentOS server)

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

只需在相同的shell脚本中编写命令:

os.system("cd /directory/path/here; run the commands")
更好的(也许)方法是使用模块:


我认为您不能在
os.system()中调用
pushd

>>> import os
>>> ret = os.system("pushd /tmp")
sh: pushd: not found
也许只是可能您的系统实际上提供了一个触发shell内部函数的
pushd
二进制文件(我想我以前在FreeBSD上见过这个),但是进程的当前工作目录不能受其他进程的影响——因此您的第一个
system()
启动一个shell,运行一个假设的
pushd
,启动shell,运行
ls
,启动shell,运行假设的
popd
。。。这些都不会相互影响


您可以使用
os.chdir(“/home/path/”)
来更改路径:

无需使用
pushd
——只需使用
os.chdir

>>> import os
>>> os.getcwd()
'/Users/me'
>>> os.chdir('..')
>>> os.getcwd()
'/Users'
>>> os.chdir('me')
>>> os.getcwd()
'/Users/me'

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())

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

import contextlib
import os


@contextlib.contextmanager
def pushd(new_dir):
    previous_dir = os.getcwd()
    os.chdir(new_dir)
    try:
        yield
    finally:
        os.chdir(previous_dir)
然后,您可以按如下方式使用它:

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

print os.getcwd() # "wherever you started"
通过使用上下文管理器,您将是异常和返回值安全的:即使您从上下文块内部抛出异常或返回,您的代码也将始终返回到它的起始位置

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

with pushd('somewhere'):
    # do something
    with pushd('another/place'):
        # do something else
    # do something back in "somewhere"

或者创建一个与“with”一起使用的类

import os

class pushd: # pylint: disable=invalid-name
    __slots__ = ('_pushstack',)

    def __init__(self, dirname):
        self._pushstack = list()
        self.pushd(dirname)

    def __enter__(self):
        return self

    def __exit__(self, exec_type, exec_val, exc_tb) -> bool:
        # skip all the intermediate directories, just go back to the original one.
        if self._pushstack:
            os.chdir(self._pushstack.pop(0)))
        if exec_type:
            return False
        return True

    def popd(self) -> None:
        if len(self._pushstack):
            os.chdir(self._pushstack.pop())

    def pushd(self, dirname) -> None:
        self._pushstack.append(os.getcwd())
        os.chdir(dirname)


    with pushd(dirname) as d:
        ... do stuff in that dirname
        d.pushd("../..")
        d.popd()

如果你真的需要一个堆栈,即如果你想做几个pushd和popd, 见上文第101段

如果没有,只需:

olddir = os.getcwd()
os.chdir('/directory/path/here')
os.system("command to sent to minecraft")
os.chdir(olddir)

我对“~/minecraft/etc”这句话有点困惑。对我来说,它看起来像是一个简单的例子,说明了
os.system
生成了一个子shell。。。执行
bash-c“pushd目录”
bash-c“popd”
将得到相同的结果。。。为什么不直接使用
os.chdir
?nvm关于混淆线,它是正在执行的
pushd
的输出,但是分析仍然有效,您的命令不起作用,因为
os.system
生成了一个子shell。。。。一旦子shell完成,pushd/popd上下文就会变得毫无意义;我最近才开始使用subprocess(这里是新的程序员,很明显),我想更好地了解它。它可以工作,但是我必须按住CTRL+C键才能返回python提示符。奇怪。值得注意的是,在以UNC路径为参数的Windows计算机上使用
pushd
,会导致Windows自动将网络驱动器映射到该路径。使用
cd
不适用于UNC路径,也不适用于
Popen
。如果需要该功能,请使用
Popen(r'pushd\\server\folder&dir&popd',shell=True)
。还要注意,
不会在Windows中分隔命令,但是
&
会。我已经看到映射Windows驱动器可能需要30秒。你真的想等你的python脚本运行那么久吗?是的。这正是我想要的。非常感谢。仅当上一个目录是另一个目录的直接父目录时,此选项才有效。@DaveKennedy,True。我想你也可以说,只有当目录是
'/directory/path/here'
时,被接受的答案才有效,不是吗?我喜欢这个想法,它更优雅,更具pythonic:)这就是我一直在寻找的。但是,如果with语句中出现异常,则不会弹出此代码,因为@contextmanager不处理异常,您需要用try来包围产量。。。finally@MaximeViargues还有contextlib
closing
方法,它可以满足try…finally的要求,只是名称选择不当,依我拙见因为popd是隐式的,所以您没有像sh脚本中那样的push/pop对称
olddir = os.getcwd()
os.chdir('/directory/path/here')
os.system("command to sent to minecraft")
os.chdir(olddir)