Могут ли две асинхронные команды подоболочки безопасно записывать в общий стандартный вывод?

У вас должна быть функция (в прошивке UEFI) для изменения порядка пунктов меню загрузки - перемещения вверх / вниз (и даже добавления новых пунктов меню загрузки).

Я говорю только о функциональности установки прошивки UEFI.

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

Поместите Linux в качестве первого (верхнего) кандидата на загрузку в загрузочных записях NVRAM. GRUB может загружать Windows по цепочке в BIOS и UEFI!

Примечание. EasyBCD не может создавать двойную загрузку Windows / Linux на UEFI. Не тратьте время зря.

4
19.08.2017, 00:53
2 ответа

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

Здесь важно то, что обе хвостовые команды записывают файловый дескриптор в один и тот же конец записи одного и того же канала.

Если да:

printf foo1 >> file1; sleep 1
printf foo2 >> file2; sleep 1
printf 'bar1\n' >> file1; sleep 1
printf 'bar2\n' >> file2

Вот увидишь:

foo1foo2bar1
bar2

Потому что так они были написаны. Вы должны убедиться, что ваши команды выводят одну полную строку за раз,и что эти строки должны быть меньше, чем PIPE _BUF (4096 байт в Linux )для гарантии того, что запись ()будет атомарной (она также может записывать более одной полной строки за раз при условии все они заполнены, и их совокупный размер меньше, чем PIPE _BUF ).

С помощью GNU grepвы можете сделать это, передав свои команды вgrep --line-buffered '^'

(tail -f./file1 | grep --line-buffered '^' &
 tail -f./file2 | grep --line-buffered '^') | cat

Это гарантирует, что вы получите один write()системный вызов для каждой строки вывода обеих команд. (В случаях, когда команды не заканчивают свою последнюю строку вывода, grepдобавит новая строка)

4
27.01.2020, 20:53

1. Плохое решение

В конфигурации по умолчанию stderr не буферизуется , а stdout буферизуется.

Таким образом, простейшее решение вашей проблемы

  1. обеспечить, чтобы используемые инструменты записывали все строки -на -строки
  2. перенаправить их вывод в stderr(>&2)

Однако это не работает, потому что эта буферизация происходит в библиотеке C, внутри процесса. Если вы перенаправите их stdout на stderr, этот stderr также не будет буферизован.

2. Лучшее решение

Направляет их вывод в процесс, который считывает все, а затем записывает их построчно. Самым простым способом было бы

tool1 | while read; do echo "$REPLY"; done & tool2 | while read; do echo "$REPLY"; done

О «красивом» параллельном выполнении нескольких команд/скриптов здесь вы можете прочитать другой мой ответ.

3. Действительное решение

К сожалению, то, как выходные данные процесса в основном буферизуются libc, т.е. это их внутренние дела, то, как они отображают свои выходные данные на write(1,...)вызовы на уровне ядра. Это зависит от них. Не меняя их, мы не можем контролировать их вывод того, что они еще не написали.

В случае, если запись происходит с FILE*механизмом libc, вам могут пригодиться функции setbuf (3)и fflush (3 ).

0
27.01.2020, 20:53

Теги

Похожие вопросы