我正在使用crontab为我的minecraft服务器运行维护脚本。大多数情况下它工作正常,除非crontab尝试使用重启脚本。如果我手动运行重启脚本,则没有任何问题。因为我认为它与路径名称有关,所以我试图确保它总是从Minecraft目录中执行任何minecraft命令。所以我在pushd / popd中包含命令:
os.system("pushd /directory/path/here")
os.system("command to sent to minecraft")
os.system("popd")
下面是一个互动会话,将我的世界排除在外。一个简单的“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
=== (使用python 2.4的CentOS服务器)
答案 0 :(得分:70)
在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)
然后您可以像以下一样使用它:
with pushd('somewhere'):
print os.getcwd() # "somewhere"
print os.getcwd() # "wherever you started"
通过使用上下文管理器,您将是异常并且返回值是安全的:即使您抛出异常或从上下文块内部返回,您的代码也将始终cd回到它的起始位置。
您还可以在嵌套块中嵌套pushd调用,而不必依赖于全局目录堆栈:
with pushd('somewhere'):
# do something
with pushd('another/place'):
# do something else
# do something back in "somewhere"
答案 1 :(得分:11)
每个shell命令都在一个单独的进程中运行。它生成一个shell,执行pushd命令,然后shell退出。
只需在同一个shell脚本中编写命令:
os.system("cd /directory/path/here; run the commands")
subprocess
模块有一个更好的(可能)方式:
from subprocess import Popen
Popen("run the commands", shell=True, cwd="/directory/path/here")
答案 2 :(得分:4)
我认为您无法在pushd
电话中致电os.system()
:
>>> import os
>>> ret = os.system("pushd /tmp")
sh: pushd: not found
也许只是你的系统实际上提供了一个触发shell内部函数的pushd
二进制文件(我想我之前在FreeBSD上看过这个 FreeBSD has some tricks like this, but not for pushd
),但是进程的当前工作目录不受其他进程的影响 - 所以你的第一个system()
启动一个shell,运行一个假设的pushd
,启动一个shell,运行{{1启动一个shell,运行一个假设的ls
......没有一个相互影响。
您可以使用popd
更改路径:http://docs.python.org/library/os.html#os-file-dir
答案 3 :(得分:4)
无需使用pushd
- 只需使用os.chdir
:
>>> import os
>>> os.getcwd()
'/Users/me'
>>> os.chdir('..')
>>> os.getcwd()
'/Users'
>>> os.chdir('me')
>>> os.getcwd()
'/Users/me'
答案 4 :(得分:4)
pushd
和popd
有一些附加功能:它们将以前的工作目录存储在堆栈中 - 换句话说,你可以pushd
五次,做一些事情,{{1五次结束你开始的地方。你没有在这里使用它,但它可能对其他人搜索这样的问题很有用。这就是你如何模仿它:
popd
答案 5 :(得分:0)
或将一个类与'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()
答案 6 :(得分:0)
如果您确实需要堆栈,即,如果您想进行多次压入和弹出操作, 参见上面的naught101。
如果没有,只需执行以下操作:
olddir = os.getcwd()
os.chdir('/directory/path/here')
os.system("command to sent to minecraft")
os.chdir(olddir)