Shell Script mktemp, каков наилучший способ создания временного именованного канала?

30

Я знаю, что лучше всего создавать временные файлы mktemp, но как насчет именованных каналов?

Я предпочитаю, чтобы все было как можно более POSIX-совместимым, но только Linux приемлемо. Как я пишу, избегать Bashisms - мой единственный жесткий критерий dash.

Дж. М. Беккер
источник

Ответы:

41
tmppipe=$(mktemp -u)
mkfifo -m 600 "$tmppipe"

В отличие от обычного создания файла, которое может быть взломано существующим файлом или символической ссылкой, создание канала имен mkfifoили базовой функции либо создает новый файл в указанном месте, либо завершается ошибкой. Нечто подобное : >fooнебезопасно, потому что если злоумышленник может предсказать вывод, mktempто злоумышленник может создать целевой файл для себя. Но mkfifo fooпотерпел бы неудачу в таком сценарии.

Если вам нужна полная переносимость POSIX, mkfifo -m 600 /tmp/myfifoона безопасна от угона, но склонна к отказу в обслуживании; без доступа к генератору случайных имен файлов вам потребуется управлять попытками повторных попыток.

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

tmpdir=
cleanup () {
  if [ -n "$tmpdir" ] ; then rm -rf "$tmpdir"; fi
  if [ -n "$1" ]; then kill -$1 $$; fi
}
tmpdir=$(mktemp -d)
trap 'cleanup' EXIT
trap 'cleanup HUP' HUP
trap 'cleanup TERM' TERM
trap 'cleanup INT' INT
mkfifo "$tmpdir/pipe"
Жиль "ТАК - прекрати быть злым"
источник
Я на самом деле уже выбрал это в качестве своего решения ранее вчера, я ждал, чтобы увидеть, если кто-то опубликовал его, или лучше. Я также чувствовал, что в моем случае это был путь. Независимо от того ... Спасибо за помощь, я ценю это.
Дж. М. Беккер
1
Не должно ли быть команда trap trap "rm -rf '$tempdir'" EXIT HUP INT TERM? Может ли trap-код создать собственную переменную?
Шесть
@Six Ваша команда будет расширяться $tempdirво время trapоценки команды, а не во время срабатывания ловушки. В этом случае это не имеет никакого значения, за исключением того, что ваш код ужасно ломается, если значение tempdirсодержит одну кавычку, тогда как мой код всегда работает.
Жиль "ТАК - перестань быть злым"
@ Жиль Это хорошая функция. Я попробовал ваш пример с одинарными кавычками без удачи, поэтому я подумал, что trap не смог оценить переменные во время выполнения. Оказалось, что my $tempdirбыл объявлен локально, и он должен быть определен глобально, чтобы trap-доступ имел к нему доступ. Имеет смысл сейчас ...
Шесть
1
@ Жиль ... до тех пор, пока $tempdir значение не изменится, что приемлемо для всех целей. Только будьте осторожны, чтобы не использовать одно и то же имя для создания нескольких временных файлов / каталогов ...
MestreLion
3

Более безопасной альтернативой является безопасное mktempсоздание каталога, затем поместите именованный канал в этот каталог rm -R $dirи в конце сделайте, чтобы избавиться от него.

Дэвид Паркс
источник
Я решил создать FIFO в mktempкаталоге, так как это был действительно единственный приемлемый ответ. На случай, если вы не заметили, @Gilles уже опубликовал этот ответ подробно.
JM Becker
2

Используйте опцию «всухую»:

mkfifo $(mktemp -ut pipe.XXX)
Полемон
источник
1
Согласно справочным страницам, использование -uопции «не поощряется».
Dogbane
@ Dogbane Так что использование -t, но пока это работает надежно, я бы пошел с этим.
Полемон
извините, где это говорит, что -tне рекомендуется?
Dogbane
2
@dogbane Если это как-то критично, я бы сделал крошечное приложение на C, вызывающее mkstemp()функцию ( linux.die.net/man/3/mkstemp ). -tВыключатель не рекомендуется, это -p, мой плохой.
Полемон
1

Вы можете использовать mktempдля создания временного файла, затем удалить его и создать именованный канал с тем же именем.

Например:

TMPPIPE=$(mktemp -t pipe.XXX) && {
    rm -f $TMPPIPE
    mkfifo $TMPPIPE
}
кендырь
источник
Удаляет ли удаление « $TMPPIPEдо mkfifo» проблему «небезопасных», связанную с выполнением TMPPIPE=`mktemp -u` ; mkfifo $TMPPIPE?
Дж. М. Беккер
1
@TechZilla mkfifoна самом деле безопасен, в отличие от обычного обычного создания файлов из оболочки. Если это не так, создание файла, то удаление его вообще не поможет (на самом деле это значительно облегчит работу злоумышленника, не требуя от него угадывать имя файла). Таким образом, ответ Dogbane работает, но создание промежуточного файла является бесполезным осложнением.
Жиль "ТАК - перестань быть злым"
1
@Gilles, вы знаете, в каком отношении на mktempстранице руководства названа -uопция «небезопасно»?
Дж. М. Беккер
@ Dogbane, я проголосовал за ваш ответ, и ваши комментарии, которые я чувствовал, были твердыми. Хотя я уже закончил это вчера ... Я просто ждал, когда кто-нибудь опубликует или мое решение, или, надеюсь, лучшее. Так что, хотя я и использовал mktemp -dвас, у вас все еще есть очки за ваш вклад Спасибо за вашу помощь, я действительно ценю это!
Дж. М. Беккер
1
@TechZilla mktemp -uнебезопасен при создании обычного файла, поскольку обеспечивает защиту от отказа в обслуживании (если генерируемое имя достаточно непредсказуемо), но не мешает злоумышленнику создать файл под носом программы. Создание fifo вместо обычного файла - это редкий случай, когда страница руководства не рассматривается.
Жиль "ТАК - перестань быть злым"
0

Используйте mkfifoили mknodв Unix, где два отдельных процесса могут обращаться к каналу по имени - один процесс может открыть его как читателя, а другой как писателя.

mkfifo my_pipe
gzip -9 -c < my_pipe > out.gz
cat file > my_pipe

Именованный канал может быть удален как любой файл:

rm my_pipe

mkfifo --mode=0666 /tmp/namedPipe
gzip --stdout -d file.gz > /tmp/namedPipe

NamedPipe можно использовать обычным файлом только для чтения один раз.

http://www.linuxjournal.com/article/2156

Никхил Мулли
источник
2
Я полностью осведомлен о именованных каналах, и mkfifo. Он не отвечает на мой вопрос о временных именованных каналах, так же как mkdirи на создание временных каталогов.
Дж. М. Беккер
2
Как это решает проблемы, связанные mktempс безопасным созданием именованного канала?
Camh
1
да ладно, лучше всего создать их в / tmp, они по определению являются временными файлами и будут удалены после перезагрузки системы. Или, еще лучше, иметь функцию оболочки, которая будет создавать namedpipe из самого mktempрезультата ( конечно, сначала удалив временный файл, а затем запустив mkfifoего). mktempтакже можно использовать для создания временного каталога, попробуйте с помощью -t -dswitch.
Nikhil Mulley