Я написал небольшой интерфейс на Python, который позволяет пользователям воспроизводить интернет-радиоканалы. Программа использует Pythons subprocess () для инициализации mplayer для настройки на канал, например:

runn = "mplayer http://77.111.88.131:8010"
p = subprocess.Popen(runn, shell=True)
pid = int(p.pid)
wait = os.waitpid(p.pid, 1)

Затем сохраняет p.pid, и когда пользователь хочет прекратить прослушивание, используется следующий код:

os.kill(p.pid, 9)

Это прекрасно работает в OpenSUSE, но не в Ubuntu. Кажется, что Ubuntu фактически запускает два отдельных процесса. Терминальный выход:

Opensuse 11.3:

$ pgrep mplayer
22845

Ubuntu 10.04:

$ pgrep mplayer
22846
22847

Это также применяется при запуске других программ. Кто-нибудь знает почему? Я действительно хочу, чтобы это приложение работало на всех дистрибутивах, поэтому любая помощь очень ценится.

4
Fredrik 12 Авг 2010 в 18:45

3 ответа

Лучший ответ

Попробуй это:

p = subprocess.Popen(runn.split(), shell=False)

Я думаю, что происходит, это ...

Когда вы говорите, что shell=True подпроцесс фактически запускает эту команду sh -c "your string". Команда sh затем интерпретирует вашу строку и запускает команду, как будто вы ввели ее в командной строке (более или менее). Обычно это приводит к двум процессам. Один будет sh -c "your string", а другой - дочерний, your string.

Некоторые версии sh имеют оптимизацию, в которой они автоматически exec выполняют команду при определенных условиях. Они делают это, если это последняя команда, которую sh собирается выполнить, и у sh нет другой причины остаться. При использовании sh -c для запуска команды это почти всегда приводит к тому, что вызов sh заменяет себя выполняемой командой, в результате чего получается один процесс.

На мой взгляд, это действительно очень плохая идея - вызывать subprocess.Popen с shell=True. Делая это, вы открываете себе массу проблем безопасности и, как правило, менее предсказуемого поведения, поскольку метасимволы оболочки интерпретируются sh -c.

6
Omnifarious 12 Авг 2010 в 15:05

subprocess.Popen возвращает объект Popen с несколько полезных методов. Вероятно, это плохая идея, чтобы прекратить вещи, используя непосредственно os.kill ...

Происходит ли то же самое, если вы используете объект Popen p.terminate () или p.kill ()?

0
Joe Kington 12 Авг 2010 в 14:53

У меня нет точного ответа, но вот несколько способов выяснить это:

Используйте pstree, чтобы проверить отношения родитель / потомок между процессами.

Используйте ps -awux для просмотра полных аргументов командной строки для всех процессов.

Обратите внимание, что использование shell=True запускает процесс оболочки (например, /bin/bash), который запускает mplayer. Это может быть еще один путь для расследования. Обе системы используют одну и ту же оболочку?

Обе системы используют одну и ту же версию mplayer? питона?

1
Daniel Stutzbach 12 Авг 2010 в 14:52