LINUX.ORG.RU

Перенаправление stdout и stderr в переменные

 ,


0

1

Привет! Есть пара вопросов по сабжу.

1. Как мне перенаправить вывод команды в отдельные переменные? Гуглятся такие варианты, но как это работает не пойму, может можно селать как-то проще?

2. При выводе в переменную с последующим ее echo у меня результат будет только как отработает команда. Можно ли как-то организовать аналог tail -f для переменной?

Все это желательно сделать без промежуточных файлов, но если не получится придется наверно делать с fifo.

Это эталонный топик для лора:
автор как обычно не описывает задачу, а описывает свои фантазии на тему как эта задача должна решаться.
Дальше начинается слёт телепатов и прочих доброжелателей

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

Вот пример

#!/bin/bash
simple_function(){
OUT=$(ping -c 4 localhost)
ERR=??? <вопрос номер 1>

echo $OUT <вопрос номер 2>

echo $ERR
}

simple_function

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

Этот то вариант очевиден

1. Как мне перенаправить вывод команды в отдельные переменные?

alozovskoy ★★★★★ ()

Эммм,

ping -q -c 5 google.com > /dev/null 2>&1
STATCODE="$?"
echo "$STATCODE"

0

#либо

ping -q -c 5 wewqreuadfhadfdgd.com > /dev/null 2>&1
STATCODE="$?"
echo "$STATCODE"

2

Success: code 0
No reply: code 1
Other errors: code 2

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

Ну тогда man mktemp, но я думаю ты и сам до этого догадаешься.

nanoolinux ★★★★ ()

По второму вопросу — coprocess, но это чёрная магия и лучше её не использовать:

#!/bin/bash

coproc ping -c 20 -n 127.0.0.1

for i in 1 2 3 4 5 6 7 8 9 A ; do
  read var <&"${COPROC[0]}"
  echo i is $i ";" var is $var
  sleep 1
done

Примеры по вашей ссылки по первому вопросу основаны на том, что можно получить stdout и stdin через Process Substitution, но это будут подпроцессы, чтобы передать значения переменных в основной процесс их выводят через ″typeset -p″, а потом превращают в переменные через ″eval″. Лично я бы предпочёл использование временных файлов ( ″mktemp″), чем через год понимать что это за код, завёрнутый в ″eval″.

mky ★★★★★ ()
Последнее исправление: mky (всего исправлений: 1)

В лоб:

capture() {
    local cmd="$1"
    local stdout="$2"
    local stderr="$3"

    local f_stdout=$(mktemp)
    local f_stderr=$(mktemp)

    $cmd >$f_stderr 2>$f_stdout

    local _ifs=$IFS
    eval "IFS= $stdout=\$(cat '$f_stdout')"
    eval "IFS= $stderr=\$(cat '$f_stderr')"
    IFS=$_ifs

    rm -f "$f_stderr" "$f_stdout"
}

capture "ping -c 3 whatever.org" PING_STDOUT PING_STDERR
echo STDOUT: $PING_STDOUT
echo STDERR: $PING_STDERR 
KennyMinigun ★★★★★ ()
Последнее исправление: KennyMinigun (всего исправлений: 1)

Нецелесообразно: на порядок сложнее временного файла.

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

Нажал ctrl-c, какие-то фалы в /tmp появились. Mожет стоит к скрпиту справку добавить, что, мол, за ним нужно подчищать?

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

Mожет стоит к скрпиту справку добавить, что, мол, за ним нужно подчищать?

Нет. Это не скрипт, а сниппет.

какие-то фалы в /tmp появились

1. /tmp за тебя система должна чистить.
2. Это не скрипт, а лишь функция. Хочешь — навесь trap на SIGTERM и любые другие (кроме немаскируемых).

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

Мало того, я сталкивался с ситуацией, когда благодаря буферному кэшу повторное чтение файла работало в 10-20 раз быстрее, чем связка «чтение в переменную - многократное echo».

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

навесь trap на SIGTERM и любые другие

Не-а, вы чего, в отличие от вас в shell-программировании не разбираюсь. Обычный пользователь. Хороший «сниппет».

anonymous ()

bash - это тебе не perl, чтобы перенаправлять в переменные.
Переменные могут хранить данные, но не могут быть объектами перенаправления. Поэтому придётся создавать временные файлы.

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