如何解决通过os.system推送
| 我正在使用crontab为我的Minecraft服务器运行维护脚本。在大多数情况下,它工作正常,除非crontab尝试使用重新启动脚本。如果我手动运行重新启动脚本,则不会有任何问题。因为我相信它与路径名有关,所以我试图确保它始终在minecraft目录中执行任何minecraft命令。所以我将命令包含在push / popd中:os.system(\"pushd /directory/path/here\")
os.system(\"command to sent to minecraft\")
os.system(\"popd\")
下面是一个互动式会议,将我的世界飞机排除在外。一个简单的“ ls”测试。如您所见,它根本不是从pushd目录运行os.system命令,而是从/ etc /运行python来说明我的观点的/ etc /目录。 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服务器)
解决方法
每个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\")
, 在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\"
通过使用上下文管理器,您将成为异常并且返回值安全:即使您抛出异常或从上下文块内部返回代码,您的代码也将始终返回到它的开始位置。
您还可以将推送的调用嵌套在嵌套块中,而不必依赖全局目录堆栈:
with pushd(\'somewhere\'):
# do something
with pushd(\'another/place\'):
# do something else
# do something back in \"somewhere\"
, 我认为您无法在os.system()
通话中致电pushd
:
>>> import os
>>> ret = os.system(\"pushd /tmp\")
sh: pushd: not found
也许只是您的系统实际上提供了一个触发外壳内部功能的ѭ8trigger二进制文件(我想我在FreeBSD上已经在FreeBSD上看到了类似的技巧,但在pushd
上却没有),但是进程的当前工作目录不能是受其他过程的影响-因此您的第一个system()
启动一个壳,运行一个假设的pushd
,启动一个壳,运行ls
,启动一个壳,运行一个假设的popd
……两者都不相互影响。
您可以使用ѭ17来更改路径:http://docs.python.org/library/os.html#os-file-dir
, 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())
, 无需使用pushd
-只需使用os.chdir
:
>>> import os
>>> os.getcwd()
\'/Users/me\'
>>> os.chdir(\'..\')
>>> os.getcwd()
\'/Users\'
>>> os.chdir(\'me\')
>>> os.getcwd()
\'/Users/me\'
, 或将一个类与\'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()
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。