web-dev-qa-db-ja.com

Pythonスクリプトがすでに実行されているかどうかを確認します

Pythonスクリプトがすでに実行されているかどうかを確認し、実行されている場合は古いプロセスを強制終了します。これを試しましたが、実際には機能しません...

import os
import subprocess
import signal

process_name = "python " + os.path.abspath(__file__)
proc = subprocess.Popen(["pgrep", process_name], stdout=subprocess.PIPE)

# Kill process.
for pid in proc.stdout:
    os.kill(int(pid), signal.SIGTERM)
    # Check if the process that we killed is alive.
    try:
        os.kill(int(pid), 0)
        raise Exception("""wasn't able to kill the process
                          HINT:use signal.SIGKILL or signal.SIGABORT""")
    except OSError as ex:
        continue

古いプロセスを強制終了することはなく、現在は複数回実行されています。

7
Martin

pgrepベースのメソッドを使用してpythonスクリプトが実行されているかどうかを判断することは、信頼できません。次に例を示します。

_> ps -ef | grep 'python sleep.py'
userid  21107  2069  0 12:51 pts/3    00:00:00 python sleep.py
userid  21292  2069  0 13:08 pts/3    00:00:00 grep python sleep.py
> pgrep 'python sleep.py'
> 
_

実行中のpythonスクリプトをその名前で識別する際の追加の問題:

  • 実際のpython文字列は、スクリプトの実行方法によって異なる場合があります。たとえば、次のようになります。

_/usr/bin/python2.7 sleep.py_

  • スクリプトが実際のファイルへのシンボリックリンクであり、両方の場所から実行できる場合、os.path.abspath(__file__)メソッドを使用してプロセス名でスクリプトを見つけると失敗する可能性があります

例:

_> cat abs_path.py
import os
print os.path.abspath(__file__)
> ls -l abs_path.py 
lrwxrwxrwx 1 userid at 15 Apr 22 13:22 abs_path.py -> bin/abs_path.py
> python abs_path.py
/home/userid/abs_path.py
> python bin/abs_path.py
/home/userid/bin/abs_path.py
_
  • プロセス(pythonスクリプトからのプロセスを含む)は、実行中に実際に名前を変更できます(スクリプトの場合はそうではないかもしれませんが、true)

このような問題に取り組む際の私の個人的な好みは、スクリプトが独自のpidを配置する一意のよく知られた場所にpidfileを作成することです。これにより、すでに実行されている可能性のあるプロセスのpidをより確実に判別できます。

Pidfileを作成し、それ自体のpidに確実に書き込む際には、競合状態を考慮する必要があります。通常、ファイルの内容を再確認し、不一致が検出された場合は自殺するだけで、プロセスの実際の名前に関係なく、実行中のプロセスインスタンスが最大で1つ存在することを確認できます。

4
Dan Cornilescu

私の現在のソリューションは次のようになります(OSX上)。正規表現と組み合わせてpgrepを使用しています

import subprocess

cmd = ['pgrep -f .*python.*testing03.py']
process = subprocess.Popen(cmd, Shell=True, stdout=subprocess.PIPE, 
stderr=subprocess.PIPE)
my_pid, err = process.communicate()

if len(my_pid.splitlines()) >0:
   print("Running")
   exit()
else:
  print("Not Running")

私がテストした限り、python文字列が異なっていても、これは機能するはずです。スクリプトの場所も重要ではありません。

3
MickeMannen

から ダンの答え 私は思いついた

> ps -f -C python | grep 'sleep.py'
userid  21107  2069  0 12:51 pts/3    00:00:00 anypath/python anypath/sleep.py

これには、前の回答で説明した多くの問題がまだありますが、少なくとも結果にgrepが表示され、スクリプトのパスに依存することはなくなります。

いくつかのpythonバージョンをチェックすることも可能です:

> ps -f -C python,python2.7 | grep 'sleepy.py'

編集:複数のpython3インスタンスが実行されている場合、これは正しく機能しません。より良い使用法:

> pgrep -a python | grep 'sleepy.py'
1
Fabian

この質問は pythonスクリプトが実行されているかどうかを確認してください

PidFile module を使用することをお勧めします。すべてを処理します。

import pidfile
import time

print('Starting process')
try:
    with pidfile.PIDFile():
        print('Process started')
        time.sleep(30)
except pidfile.AlreadyRunningError:
    print('Already running.')

print('Exiting')

2つの端末でこのスクリプトを2回実行してみてください

私は図書館の所有者とは関係ありません、私はちょうどそれを見つけました

0
aster94