2

私が知る限り、Python でシステム コマンドを実行するには 3 つの方法があります。

  1. os.system(command) -> exit_status

  2. os.popen(command [, mode='r' [, bufsize]]) -> pipe

  3. commands.getoutput(command)-> string

次に、システム コマンドのエグゼキュータを次のように制御する必要があります。

os.system('su xxx;' + command)

同じ効果を達成するための他のよりエレガントな方法はありますか?

4

3 に答える 3

2

あなたが言及したすべてのこと (subprocessちなみに、モジュールによって継承されています) は、プロセスを生成する方法です。を探しているようですねsetuid。それを行う関数を呼び出すことができます (例: os.setuid)。または、スクリプトの内容によってはよくあることですが、昇格したユーザーとしてスクリプト全体を実行することもできます。

于 2012-07-26T04:16:51.570 に答える
1

subprocessモジュールを使用して別のユーザーとしてコマンドを実行します ( @Julian の提案を実装します)。@tMC のコードに似ていますが、より高いレベルです。

import os
import pwd
from subprocess import check_output as qx

def change_user(uid, gid=None):
    if gid is None:
        gid = uid
    def preexec_fn():
        os.setgid(gid)
        os.setgroups([gid])
        os.setuid(uid)
    return preexec_fn

print(qx(['id']))
print(qx(['id'], preexec_fn=change_user(pwd.getpwnam('nobody').pw_uid), env={}))
print(qx(['id']))

close_fds=True古い Python バージョンでは、fd リークを避けるためにサブプロセス呼び出しを追加する必要がある場合があります。

引数を使用cwdして、コマンドを実行するディレクトリ (ユーザーのホーム ディレクトリなど) を指定できます。

envサブプロセスの環境変数を設定するためにディクショナリにデータを入力します。

于 2012-07-27T08:56:53.777 に答える
0

ほとんどの実装では「低レベル」になる可能性がありますが、高レベルのモジュールでこれが実際にどのように発生するかを理解することは、一部の人にとっては教育的かもしれません。

import os
import pwd

pout, pin = os.pipe()                                # Creates an anonymous pipe used to communicate with the child process

if not os.fork():                                    # The fork() syscall duplicated the process retuning 0 to the new child process.
    os.closerange(0, 2)                              # Closing stdin, stdout and stderr- they were inherited from the parent process
    os.dup2(pin, 1)                                  # Copy the input side of the IPC pipe to stdout (always fd 1)
    os.setuid(pwd.getpwnam('nobody').pw_uid)         # Change our user id to that of the user `nobody`.  Also see `setgid()`
    os.execl('/bin/whoami', 'whoami')                # Now that we've connected out stdout to the pipe connected to the parent process
                                                     #     and changed our user id to that of the user we want to run the command with
                                                     #     we can `exec()` the new process; replacing our currently running process, 
                                                     #     inheriting the env.
    os._exit(0)                                      # Since we called `exec` above, this is never eval'd, but is good form

os.wait()                                            # Back at the parent process- `wait()` will, well, wait until the child process exits.
os.close(pin)                                        # Close the input side of the pipe, the parent shouldn't write to. (bi-dirctional IPC
                                                     #     would require 2 pipes.  One in each direction
child_stdout_pipe = os.fdopen(pout, 'r')             # Open the output side of the IPC pipe
child_process_output = child_stdout_pipe.read()      # ...and read from the pipe.  This should include anything that came from the stdout of
                                                     #     the child process.  Since we closed the input side of the pipe, the `read()` 
                                                     #     will read an EOF after all the data in the pipe is returned.

print child_process_output                           # Win! (`write()`ing out the parent stdout want we found in the pipe from the child proc
于 2012-07-26T19:21:45.547 に答える