Судо Ренис в питоне

В общем, это хороший вопрос. Linux не позволяет непривилегированным пользователям снижать привлекательность PID, и запускать все с правами root - это возможность для червей.

Тем не менее, вот мои особенности: у меня есть учетная запись пользователя, которая управляет несколькими процессами, который имеет пароль sudo привилегии для renice и несколько других команд, которые он использует. У меня также есть скрипт, который является общей точкой входа для всех пользователей в этой системе. Этот скрипт может запускать как обычные пользовательские программы, так и процессы, управляемые специальной учетной записью. Таким образом, скрипт при запуске с определенной опцией должен renice если он может, но молча терпит неудачу, если не может.

Код, который я получил для этого, выглядит так:

subprocess.Popen(["sudo", "renice", "-20", str(process.pid)],
#                shell = True,
                 stdout = subprocess.DEVNULL,
                 stderr = subprocess.STDOUT)

Если у меня есть shell = True закомментировано, процесс приобретает новую привлекательность, но если я работаю как непривилегированный пользователь, sudo выбрасывает запрос на ввод пароля и портит вывод моего терминала. Нажатие клавиш становится невидимым, и все выглядит глупо. Если я раскомментирую shell = TrueЯ не получаю вывод терминала. Однако процесс не меняет свою привлекательность, даже если я запускаю его как root.

Поврежденный вывод терминала вполне может быть связан с эмулятором терминала, который я использую (не пробовал его с другим), но я хочу объединить эти варианты поведения. Тишина от sudo несмотря ни на что, но приятность изменится, если пользователь может успешно выполнить sudo.

Есть указатели?

1 ответ

Решение

Я думаю это потому что sudo требуется TTY, даже если пароль не требуется.

Попробуйте предоставить один:

import os
import pty
import subprocess

master, slave = pty.openpty()
p = subprocess.Popen(
    ["sudo", "id", "-a"],
    stdin=slave, stdout=slave, stderr=slave
)
os.close(slave)

output = os.read(master, 1026)
os.close(master)
print(output)

Код выше должен напечатать что-то вроде uid=0(root) gid=0(root) groups=0(root), Если это так, то заменить id с reniceудали ненужное os.read и тебе должно быть хорошо.

Обновление: в случае с OP он потерпел неудачу по другой причине. Добавление start_new_session=True в Popen он молча провалился для непривилегированных пользователей и преуспел в качестве пользователя root.

Другие вопросы по тегам