Python で GTK GUI アプリケーションを作成して、シェル スクリプトを呼び出し、呼び出しパラメーターを GUI からスクリプトに渡し、スクリプトの結果をテキスト ウィンドウに返すようにしました。
ここで、ユーザーが実行中のシェル スクリプトを GUI からキャンセルできるようにしたいと考えています。スクリプトは Popen で開始されます。通常のユーザーとして呼び出すと、正常に動作します (以下のコードではフラグ sudo=False)。sudo を使用してスクリプトを呼び出すと、キャンセルできなくなります。shell=True を使用すると kill が機能しないという報告があったので、shell=False でテストしましたが、どちらも機能しません。
問題を次のコード スニペットに落とし込みました。
import os
import signal
import subprocess
import time
import sys
import shlex
bashScriptFileName="t.sh"
f = open(bashScriptFileName,'w')
f.write("""#!/bin/bash
on_die()
{
echo "Dying..."
exit 0
}
trap 'on_die' TERM
SEC=0
while true ; do
sleep 1
SEC=$((SEC+1))
echo "I'm PID# $$, and I'm alive for $SEC seconds now!"
done
exit 0""")
f.close()
os.chmod(bashScriptFileName, 0755)
shell=True # flag to enable/disable shell invocation of Popen
sudo=True # flag to invoke command with sudo
if sudo:
commandToExecute='sudo -S '+ bashScriptFileName
else:
commandToExecute='./' + bashScriptFileName
if not shell:
commandToExecute = shlex.split(commandToExecute)
print "Command: %s" % (commandToExecute)
proc = subprocess.Popen(commandToExecute, stdin=subprocess.PIPE, close_fds=False,shell=shell, preexec_fn=os.setsid)
print >> proc.stdin, "secretPassword"
print 'PARENT : Pausing before sending signal to child %s...' % proc.pid
sys.stdout.flush()
time.sleep(5)
print 'PARENT : Signaling child %s' % proc.pid
sys.stdout.flush()
os.killpg(proc.pid, signal.SIGTERM)
time.sleep(3)
print "Done"
実際には、os.kill を使用して通常のユーザーとしてスクリプトをキャンセルするという問題がすでに発生していましたが、実行中のシェルを強制終了するには os.setuid と killpg を使用する必要があることがわかりました。私はスレッディングに慣れていません。それは、私の側から見た単純な Linux スレッディングの誤解にすぎない可能性があります ...