Как избавиться от синтаксической ошибки, возникающей при использовании нескольких одинарных кавычек в команде

У меня есть команда для получения времени последнего входа в систему определенного пользователя ubuntu, и мне нужен вывод, чтобы сохранить его в другом месте, поэтому, когда я запускаю это в моем скрипте python, я получаю синтаксическую ошибку, но когда я ssh на удаленном сервере и выполняю команда, нет проблем.

# last logged in time of ubuntu user

user_login = os.popen('ssh -i /Users/abcxyz/keypair ubuntu@1#.###.##.# lastlog -u 'ubuntu' | grep -v Latest | awk '{$1 = "";$2 = "";$3 = "";print $0 }'').read()

print(user_output)

когда я просто запускаю это в своем терминале, он отлично работает и дает мне результат:

ssh -i /Users/abcxyz/keypair ubuntu@1#.###.##.# lastlog -u 'ubuntu' | grep -v Latest | awk '{$1 = "";$2 = "";$3 = "";print $0 }'

Выход: Sat Nov 17 16:32:10 +0000 2018

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
338
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Поскольку внутри вашей строки есть как одинарные, так и двойные кавычки, я бы заключил все в тройные кавычки

user_login = os.popen("""ssh -i /Users/abcxyz/keypair ubuntu@1#.###.##.# lastlog -u 'ubuntu' | grep -v Latest | awk '{$1 = "";$2 = "";$3 = "";print $0 }'""").read()

В противном случае, как написано, некоторые одинарные кавычки внутри вашей строки завершают строку полной длины посередине.

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

Charles Duffy 28.11.2018 19:24

Идеально, вы должны сконструировать это так, чтобы вообще не подвергать вас проблеме, то есть позволить интерпретатору Python выполнить работу по генерации строки, заключенной в правильные кавычки (а затем повторно цитируя ее в смело переходите на ssh).

try:
  from shlex import quote # Python 3
except ImportError:
  from pipes import quote # Python 2
import subprocess

# specify your commands the way they're actually seen by the operating system -- with
# lists of strings as argument vectors.
rmt_pipeline = [[ 'lastlog', '-u', 'ubuntu' ],
                [ 'grep', '-v', 'Latest' ],
                [ 'awk', '{$1 = "";$2 = "";$3 = "";print $0 }' ]]

# ...then, let shlex.quote() or pipes.quote() determine how to make those lists be valid
# shell syntax, as expected by the remote copy of sh -c '...' invoked by ssh
rmt_pipeline_str = ' | '.join(' '.join(quote(word) for word in piece)
                              for piece in rmt_pipeline)

# ...finally, generate the argument vector for our local copy of ssh...
ssh_cmd = [ 'ssh', '-i', '/Users/abcxyz/keypair', rmt_pipeline_str ]

# and actually invoke it.
user_output = subprocess.Popen(ssh_cmd, stdout=subprocess.PIPE).stdout

Если вы В самом деле хотите использовать os.popen() - чего не следует, как документация Python явно предлагает использовать subprocess вместо - вы можете заменить последнюю строку на:

ssh_cmd_str = ' '.join(quote(word) for word in ssh_cmd)
user_output = os.popen(ssh_cmd_str)

В операционных системах семейства UNIX все выполнение программ происходит через системный вызов execve(), который передает список строк C. Указание этого списка самостоятельно дает вам максимально возможный контроль над тем, как происходит выполнение, и предотвращает атаки путем инъекции оболочки (когда пользователь, уполномоченный предоставить параметр одной из запущенных вами программ, передает содержимое, которое интерпретируется оболочкой как синтаксис, а не data, и вместо этого запускает совершенно другую программу или косвенную операцию).

Большое спасибо за то, что поделились кодом и подробным объяснением :) ценю это.

nlp 28.11.2018 21:26

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