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」テスト。ご覧のとおり、プッシュされたディレクトリからos.systemコマンドを実行するのではなく、実行していたディレクトリである/ etc /から実行しますpython 。明らかにpushedは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
===(CentOSサーバーpython 2.4)
各シェルコマンドは、個別のプロセスで実行されます。シェルを生成し、pushdコマンドを実行してから、シェルを終了します。
同じシェルスクリプトでコマンドを書くだけです。
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"
コンテキストマネージャーを使用すると、例外と戻り値が安全になります。例外をスローしたり、コンテキストブロック内から戻ったりしても、コードは常に元の場所にcdで戻ります。
グローバルディレクトリスタックに依存せずに、ネストされたブロックにプッシュされた呼び出しをネストすることもできます。
with pushd('somewhere'):
# do something
with pushd('another/place'):
# do something else
# do something back in "somewhere"
pushd
とpopd
には、いくつかの追加機能があります。以前の作業ディレクトリをスタックに格納します。つまり、pushd
を5回実行し、いくつかの処理を実行して、popd
5回、開始した場所に到達します。ここでは使用していませんが、このような質問を検索している他の人にとっては役立つかもしれません。これはあなたがそれをエミュレートする方法です:
# 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())
os.system()
呼び出し内からpushd
を呼び出すことはできないと思います。
_>>> import os
>>> ret = os.system("pushd /tmp")
sh: pushd: not found
_
たぶん、あなたのシステムが実際にシェル内部関数をトリガーするpushd
バイナリを提供しているのかもしれません(私はこれをFreeBSDで以前に見たことがあると思いますFreeBSDにはこのようなトリックがいくつかありますが、pushd
にはありません)が、現在の作業ディレクトリプロセスは他のプロセスの影響を受けません-したがって、最初のsystem()
はシェルを開始し、仮想のpushd
を実行し、シェルを開始し、ls
を実行し、シェルを開始し、実行します架空のpopd
...どれも互いに影響しません。
あなたはできますos.chdir("/home/path/")
を使用してパスを変更します: http://docs.python.org/library/os。 html#os-file-dir
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()