Как установить определенные права доступа к файлу при перенаправлении вывода?

12

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

Я запускаю команду в оболочке bash. Я хочу перенаправить вывод, чтобы добавить к файлу, который, вероятно, не существует при первом запуске. Я хочу установить определенный режим доступа к файлам, если перенаправление вывода должно создать этот файл. Есть ли способ сделать это с помощью одной команды?

Например, я мог бы попробовать

foo >> /tmp/foo.log 0644

где 0644разрешения я хочу foo.logв конечном итоге. Большинство команд, с которыми я экспериментировал в bash, интерпретируются 0644как дополнительный аргумент foo.

У меня такое ощущение, что для chmodполучения разрешения потребуется вторая команда до или после записи в нее.

Я использую GNU Bash 4.2.25 и Ubuntu 12.04, если это имеет значение - общие ответы предпочтительнее.

Патрик М
источник

Ответы:

5

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

if [ -e /tmp/foo.log ]; then
    foo >> /tmp/foo.log
else
    foo >> /tmp/foo.log
    chmod 0644 /tmp/foo.log
fi
terdon
источник
Спасибо, Словаки, это была моя догадка. Я собираюсь оставить это открытым в течение нескольких дней, в надежде привлечь гуру, чтобы просветить нас.
Патрик М,
3
Проблема этого подхода заключается в том, что он создает короткое временное окно, когда права доступа к файлу неверны. Я бы не стал его использовать, если целью является защита конфиденциальных данных.
Проски
1
Этот ответ работает, насколько это возможно, но @proski прав: umaskответы лучше, и один из них должен быть принят.
Скотт
15

Я знаю, что это старый вопрос, но я хотел добавить свои два цента.

У меня была та же идея, и я предложил решение, похожее на BowlesCR . Проблема с его решением состояла в том, что моя команда ( foo) не сработала бы, если бы я изменил umask перед его запуском, так что это мое решение проблемы:

foo | ( umask 0033; cat >> /tmp/foo.log; )

Здесь umaskвлияет только перенаправление foo.logв подоболочку. Все остальное остается неизменным.

Немного запутанный, но это работает.

xynomorf
источник
Очень красиво и эффективно :) Просто нельзя использовать с перенаправлением stderr поверх stdout redir.
Орсирис де Йонг
5

Без настоящих сценариев вы можете немного цепляться:

touch /tmp/foo.log; chmod 0644 /tmp/foo.log; foo >> /tmp/foo.log

Эффективно похоже на ответ Словки , но сжато в одну строчку .

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

(umask 0033 && foo >> /tmp/foo.log)

Две проблемы с этим, хотя.

  1. Umask не может поднять разрешения выше уровня, указанного в creat()системном вызове (похоже, что Bash использует 0666).
  2. Это не изменит разрешения для существующего файла (поскольку umaskприменяется только к созданию файла ).
BowlesCR
источник
Я все еще новичок, чтобы * nix, что umask все еще немного волшебства для меня. Спасибо за совет, я обязательно прочитаю.
Патрик М
Хм ... Все еще позволяет непривилегированному процессу открывать файл и позже читать его содержимое.
Feuermurmel
(1) Поздравляем с поиском интересного, полезного использования cat. (Хотя это не соответствует стандартному шаблону бесполезного использования  cat.) (2) Я предполагаю, что вы хотели сказать, что bash по умолчанию использует режим  0666 при создании файлов, и поэтому я отредактировал ваш ответ, чтобы сказать так. (Смотрите это ,  это   ... (продолжение)
Скотт
(Продолжение) ... и  это .) И в этом вопросе конкретно упоминается режим 0644. Таким образом, umaskзначение 22, 23 или 32 также будет работать, в этом контексте (вам не нужно использовать ведущий ноль (и); когда режимы и  umaskзначения указываются численно, они всегда интерпретируются как восьмеричные).  22 чаще, традиционно используется.
Скотт
@Feuermurmel: И что? Вопрос явно требует режима 644. Мы должны предположить, что ОП знает, что 644 означает «читаемый мир» и предназначен для обнародования его информации.
Скотт
1

Когда перенаправление устанавливает неправильные разрешения, например:

$ rm capture.*
$ perl -e 'print STDERR "$$ STDERR\n"; print STDOUT "$$ STDOUT\n"' \
                            >> capture.STDOUT 2>> capture.STDERR
$ perl -e 'print STDERR "$$ STDERR\n"; print STDOUT "$$ STDOUT\n"' \
                            >> capture.STDOUT 2>> capture.STDERR
$ ls -l capture.*
-rw-rw-rw- 1 jcookinf jcookinf 22 Jun 12 10:38 capture.STDERR
-rw-rw-rw- 1 jcookinf jcookinf 22 Jun 12 10:38 capture.STDOUT
$ cat capture.*
215 STDERR
216 STDERR
215 STDOUT
216 STDOUT

Я полагаю, что вы можете использовать что-то, что дал xynomorf, и решить проблему с stderr от Орсириса де Йонга с небольшой модификацией, чтобы использовать замену процесса bash .

$ rm capture.*
$ perl -e 'print STDERR "$$ STDERR text\n"; print STDOUT "$$ STDOUT text\n"' \
            > >(umask 0033; cat >> capture.STDOUT) 2> >(umask 0033; cat >> capture.STDERR)
$ perl -e 'print STDERR "$$ STDERR text\n"; print STDOUT "$$ STDOUT text\n"' \
            > >(umask 0033; cat >> capture.STDOUT) 2> >(umask 0033; cat >> capture.STDERR)
$ ls -l capture.*
-rw-r--r-- 1 jcookinf jcookinf 32 Jun 12 10:43 capture.STDERR
-rw-r--r-- 1 jcookinf jcookinf 32 Jun 12 10:43 capture.STDOUT
$ cat capture.*
233 STDERR text
238 STDERR text
233 STDOUT text
238 STDOUT text

Естественно, используйте, umask 0077чтобы получить режим 600 и запретить другим пользователям просматривать содержимое.

piCookie
источник
0

Если вы хотите перенаправить в скрипт, в отличие от этого umask, с подстановкой процесса, и installвы также можете установить бит выполнения:

install -m 755 <(echo commands go here) newscript

<()помещает вывод во временный файл, см. Process-Substitution

laktak
источник