LINUX.ORG.RU

получение URL при выводе команды терминала

 


0

1

Вывод команды в терминале:

 # ./cloudflared-linux-arm64 tunnel login
Please open the following URL and log in with your Cloudflare account:
https://dash.cloudflare.com/argotunnel?callback=https%3A%2F%2Flogin.cloudflareaccess.org%2FES4Xk39csUQbzK8SnGjmM8U4vEvEXyAG81QCs9nmRmo%3D
Leave cloudflared running to download the cert automatically.

И при этом терминал в состоянии ожидания, (пока в браузере не открыть URL) т.е. невозможно параллельно перенаправить вывод в файл и потом разобрать этот файл c помощью python для получения второй строчки с URL. Т.е. если использовать например

 # ./cloudflared-linux-arm64 tunnel login | tee log.txt

файл создается, но нулевой длины. Как в подобных случаях можно использовать python для запуска команды терминала и получения URL в переменную?

Используйте pexpect, чтобы Ваш скрипт притворился терминалом, внутри которого запущена программа, но готовьтесь к боли. У cloudflared точно нет какого-нибудь API для этого? Или возможности подсунуть ему ключ заранее?

anonymous
()
Ответ на: комментарий от anonymous

Cloudflare API есть, а Cloudflared не наблюдается.

zorinquen
() автор топика

файл создается, но нулевой длины

Если cloudflared-linux-arm64 не пишет в stderr, то запускай её через stdbuf:

stdbuf -oL ./cloudflared-linux-arm64 tunnel login | tee log.txt

Впрочем, если прогрмма пишет в stderr, то stdbuf тоже может понадобиться. Читай man stdbuf, если что.

anonymous
()

запускай из питона с помощью popen, и читай его вывод, например

from subprocess import Popen, PIPE
pipe = Popen(["ping", "yandex.ru"], stdout=PIPE)
pipe.stdout.read1(200) # pipe1 читает сколько доступно, но не более N, для синхронного-буферизованного чтения нужно использовать read(), который либо будет ждать завершения или переполнения буфера канала, либо если указать N, то будет ждать пока не станет доступно N байт

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

AKonia ★★★
()
Последнее исправление: AKonia (всего исправлений: 6)
Ответ на: комментарий от AKonia

Ваш пример кода вообще рабочий, но в моем случае почему-то после последней команды тишина:

>>> from subprocess import Popen, PIPE
>>> pipe = Popen(["cloudflared", "tunnel", "login"], stdout=PIPE)
>>> A browser window should have opened at the following URL:

https://dash.cloudflare.com/argotunnel?callback=https%3A%2F%2Flogin.cloudflareaccess.org%2F0e5Ub5U9bn6HId0hqCK8x2vJ4svQs7WhfXLFMAd19Wk%3D

If the browser failed to open, please visit the URL above directly in your browser.

>>> pipe.stdout.read1(600)
2022-02-05T15:29:05Z INF Waiting for login...

zorinquen
() автор топика
Ответ на: комментарий от zorinquen

Waiting for login…

Полагаю, что то с авторизацией, но что подсказать не смогу, возможно с правами что-то не так или что-то ещё. Плюс к тому же у вас отличается схема запуска, т.к. ["cloudflared", "tunnel", "login"] раскроется в cloudflared tunnel login, тогда как в вопросе было ./cloudflared-linux-arm64 tunnel login, т.е. если есть симссылка и запуск из $PATH, то наверное проблема не в этом, но если это другой бинарник или даже сценарий-обёртка, то возможно проблема из-за этого. Если вы уверены, что исходная команда работала без проблем, то нужно просто и для питона создать такие же условия.

AKonia ★★★
()
Последнее исправление: AKonia (всего исправлений: 1)
Ответ на: комментарий от AKonia

нет, это просто другой бинарник для x86/64. А строка

2022-02-05T15:29:05Z INF Waiting for login...

означает ожидание пока юзер не введет имя и пароль во вновь открытой вкладке браузера. C бинарником cloudflared-linux-arm64 то же самое.

zorinquen
() автор топика
Ответ на: комментарий от zorinquen

Ну так ввели ? Или логин и пароль не обязательны и система должна сама по себе работать ? Если просто запустить разве не то же самое выдаёт ? Плюс посмотрите ещё и pipe.stderr может в нём написано, что какая-то ошибка есть.

AKonia ★★★
()
Ответ на: комментарий от AKonia

нет, в pipe.stderr тоже самое - тишина. Я не вводил имя и пароль в браузере - я планирую автоматизировать в скрипте. Мне нужно промежуточный URL

https://dash.cloudflare.com/argotunnel?callback=https%3A%2F%2Flogin.cloudflareaccess.org%2F0e5Ub5U9bn6HId0hqCK8x2vJ4svQs7WhfXLFMAd19Wk%3D

получить в переменную.

Может это действительно сложновато и возможно как-то API использовать от cloudflared…

zorinquen
() автор топика
Ответ на: комментарий от AKonia

подпроцесс

Подпроцесс наследует дескрипторы, иначе как бы он мог писать в ту же консоль.

anonymous
()
Ответ на: комментарий от zorinquen

Интересные дела. Поискал в интернете, находки подтверждают мою гипотезу: https://github.com/cloudflare/cloudflared/blob/235897ba217f88d75d48cf4b17400af1e201ccec/token/transfer.go#L43 — программа пишет в stderr.

Другое дело, почему не сработало перенаправление? Точнее, почему не создался файл — вот что странно! Запуск просто tee log.txt, без других программ и пайпов создаёт файл в любом случае. Не вижу причины, почему бы моя конструкция не сработала. Ну да ладно, разберёмся с этим в следующий раз.

Давай попробуем с питоном ещё разок. Если ты хочешь читать из stderr процесса, то при его создании его стандартный поток ошибок тебе тоже нужно перенаправить:

cfd_proc = Popen(["cloudflared", "tunnel", "login"], stdout=PIPE, stderr=PIPE, text=True)

Я добавил stderr=PIPE для перенаправления и text=True, чтобы читать сразу строки, а не байтики. Теперь, чтобы прочитать из этого пайпа, соответственно, нужно использовать методы объекта cfd_proc.stderr, например, тебе будет удобно использовать readline(), чтобы читать построчно:

line1 = cfd_proc.stderr.readline()
url = cfd_proc.stderr.readline()

Сработало?

Но управлять внешним процессом, со всеми его особенностями, не так-то просто. Этот, вон, браузеры запускает, ждёт чего-то… Как ты это в скрипте будешь обрабатывать? Я не говорю, что это невозможно, даже дам пару ссылок полезных: https://docs.python.org/3/library/subprocess.html, https://docs.python.org/3/library/select.html. Однако, у Cloudflare есть официальное API и написанный на питоне интерфейс к нему: https://github.com/cloudflare/python-cloudflare. Ты посмотри, может так будет проще. А ещё посмотри сторонние проекты на Гитхабе по запросу «cloudflare», там много интересного бывает.

anonymous
()
Ответ на: комментарий от anonymous

спасибки, наверное действительно с помощью официального API будет проще…

zorinquen
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.