Может ли программа определить, запущена ли она через оболочку или нет? - PullRequest
0 голосов
/ 20 февраля 2020

Команда ls дает мне другой стандартный вывод , если для shell установлено значение true. Почему это так?

Существует ли базовая концепция, позволяющая программе (в данном случае ls) определять, запущена ли она через оболочку или нет?

Я заметил, что и p1, и p2 используют один и тот же стандартный вывод в Windows, но не в Linux.

import subprocess

cmd = ['ls', '-la']
# Using shell
p1 = subprocess.run(executable=cmd[0], args=cmd[1:], shell=True, text=True, capture_output=True)
# Without using shell
p2 = subprocess.run(executable=cmd[0], args=cmd[1:], shell=False, text=True, capture_output=True)

print(p1.stdout)
print(p2.stdout)

Выход на Linux

total 12
drwxr-xr-x  2 root root 4096 Feb 20 18:25 .
drwx------ 10 root root 4096 Feb 20 18:51 ..
-rw-r--r--  1 root root  269 Feb 20 18:57 test.py

test.py

Ответы [ 2 ]

1 голос
/ 20 февраля 2020

Документация Python нечеткая, но поведение не может скрыться от strace.

Ваш Python код:

cmd = ['ls', '-la']
p1 = subprocess.run(executable=cmd[0], args=cmd[1:], shell=True, text=True, capture_output=True)
p2 = subprocess.run(executable=cmd[0], args=cmd[1:], shell=False, text=True, capture_output=True)

Превращается в (strace -f -e execve python3 foo.py ):

[pid 143557] execve("/bin/ls", ["ls", "-c", "-la"], 0x7fffc1235340 /* 34 vars */) = 0
[pid 143558] execve("/bin/ls", ["-la"], 0x7fffc1235340 /* 34 vars */) = 0

Что эквивалентно выполнению этих команд оболочки, что, как вы можете подтвердить, дает тот же результат, даже если обе они выполняются из оболочки.

ls -c -la           # Generally equivalent to: ls -lca
( exec -a -la ls )  # Generally equivalent to: ls

Из этого мы может вывести поведение.

Если shell=True, вызывается executable. Список аргументов - это executable, за которым следует стандартный флаг оболочки -c, за которым следует args. Это имеет больше смысла в случае executable='bash', args=['ls -la'].

Если shell=False, исполняемый файл вызывается. Список аргументов args. Это имитирует execve.

Так что по сути нет, здесь никакого обнаружения не происходит. Это просто два разных вызова ls, и ни то, ни другое вы не хотели.

0 голосов
/ 20 февраля 2020

Невозможно определить , посмотрев на возвращаемое значение вызова run(), как вы.

Возвращаемое значение (p1, то есть CompletedProcess) не хранит атрибут для оболочки:

>>> p1.__dict__
{'args': 'ls', 'returncode': 0, 'stdout': None, 'stderr': None}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...