bash :состояние гонки с заменой трубопровода, тройника и процесса

Здесь у вас две проблемы. Во-первых, ваш исходный путь вряд ли будет правильным. Если имя файла на самом деле не начинается с точки, похоже, что вы пытаетесь указать текущий каталог, но не включаете косую черту между точкой и именем файла.

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

cp ArtTunnel.jpg../steph/

Обратите внимание, что «./» не требуется перед именем файла ArtTunnel.jpg, когда вы выполняете эту команду из того же каталога, в котором в данный момент находится файл.

3
09.12.2019, 21:56
2 ответа

В некоторых версиях Bash есть ошибка, из-за которой они не ожидают должным образом процессы, порожденные подстановкой процессов.

0
27.01.2020, 21:20

Вызов dumpв замене процесса выполняется как асинхронный процесс. Это означает, что teeзаписывает в него свои выходные данные, после чего конвейер завершает работу. Конвейер завершает работу, потому что вывод из teeбуферизуется; если вы запишете больше данных, чем размер конвейерного буфера , teeпридется ждать, пока dumpне воспользуется ими, и ваш исходный код, вполне возможно, будет работать.

Предполагая, что вы записываете только небольшой объем данных, как вы делаете в вопросе, вы затем читаете из a.txtсразу после завершения конвейера, до того, как dumpсможет записать что-либо в файл (он все еще спит в фоновом режиме, а данные висят в конвейерном буфере ).

Если вы посмотрите на файл a.txtпосле запуска ошибочного кода, вы заметите, что он содержит строку twice.Таким образом, в конце концов, после небольшой задержки, обеспечиваемой sleep 1в функции, он туда попадает.

Чтобы предотвратить преждевременное завершение конвейера, добавьте catв конце:

dump() {
    (sleep 1; cat) > "$1"
}

(sleep 0; echo "twice") | tee >(dump "./a.txt") | cat
echo "$(< "a.txt")"

Это заставляет его работать, потому что теперь процесс catдолжен ждать, пока выходные данные dumpпоступят по каналу (их не будет, но он не знает, что ). Это задерживает завершение конвейера до возврата вызова dump. В этот момент данные уже были записаны в a.txtи могут быть получены последней командой сценария.

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

catпо умолчанию читает со стандартного ввода. Стандартный вход добавленного catсвязан со стандартным выходом teeи с заменой процесса на dumpна предыдущем шаге конвейера. Утилита catбудет читать до тех пор, пока больше нечего читать. Этого не произойдет, пока оба teeи dumpне завершат выполнение.


Подчищенная версия кода:

dump() {
    sleep 1
    cat >"$1"
}

echo twice | tee >(dump./a.txt) | cat

cat a.txt
2
27.01.2020, 21:20

Теги

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