2016-09-29 6 views
2

В bash, я хочу запустить свою программу (gollum) и использовать часть stderr (номер порта) в качестве аргумента для другой программы. Я перенаправляю stderr на stdout и использую grep и sed для фильтрации вывода. Я получаю результат в стандартный вывод:Трубопровод из долговременного процесса в xargs без эффекта

gollum -p0 2>&1| sed -n -e "s/.*port=//p" 

возвращает «56343» и продолжать работать, как Голлум является сервером.

Однако, если я хочу использовать это как аргумент другой программы (т. Е. Эхо, но я хочу использовать его позже, чтобы запустить интернет-навигатор с номером порта) с xargs, он не работает.

gollum -p0 2>&1| sed -n -e "s/.*port=//p" | xargs -n1 echo 

Ничего не происходит. Вы знаете, почему, или у вас есть другая идея сделать то же самое.

Благодарим за помощь.

+1

Является ли проблема, что Баш ждет, пока все дети в конвейере умрут, и 'gollum' не умрет (одно кольцо держит его в живых)? –

+0

На самом деле это потому, что голлум не умирает. Я убиваю из других мест, и это работает. Как я могу сделать свою вторую программу, как только номер порта будет возвращен? –

+1

Если 'gollum' не имеет возможности запускаться в режиме« демона », тогда' (gollum -p0 2> & 1 &) | sed ... | xargs ... ', предполагая, что вы должны использовать' xargs'. Подоболочка для '(...)' не ждет, пока 'gollum' умрет. Тем не менее, у вас может быть проблема с 'sed', а не умиранием; возможно, вы будете использовать 'sed -n -e '/ port =/{s /.* port = //; p; q;}'' для остановки после первой строки порта. Я думаю, вам нужны оба уловки; вам нужен процесс, который запускает «gollum», чтобы умереть, и «sed», который анализирует выход, чтобы умереть. –

ответ

2

Это легко сделать, если вы не хотите, чтобы ваш сервер работал в фоновом режиме. Если вы это сделаете, один подход заключается в использовании процесса замещения:

#!/bin/bash 
#  ^^^^- not /bin/sh; needed for >(...) syntax 

gollum -p0 > >(
    while IFS= read -r line; do 
    # start a web browser here, etc. 
    [[ $line = *"port="* ]] && echo "${line##*port=}" 
    # ...for instance, could also be: 
    # open "http://localhost:${line##*port=}/" 
    done 
) 2>&1 & 

... если вы хотите читать только первую строку, содержащую port=, затем break из цикла в обработчике, и справиться с остальными от stdin перед его выходом (это так же просто, как с использованием cat >/dev/null).

+0

Спасибо, возможно, работает, но я надеялся что-то проще. –

+2

Существует разница между «простыми» с точки зрения легко читаемого и «простого» с точки зрения очень четкого поведения. Часто в bash вы можете иметь одну форму простоты или другую, но не обе. –