8

This is probably a duplicate, but all my searches are turning up questions about permission denied errors.

I am running a command in a bash shell. I want to redirect output to append to a file that probably does not exist on the first run. I want to set specific file permissions mode if output redirection has to create this file. Is there a way to do this with one command?

For example, I might try

foo >> /tmp/foo.log 0644

where 0644 are the permissions I want foo.log to end up with. Most commands I've experimented with in bash end up interpreting 0644 as an additional argument to foo.

I get the feeling that this is going to take a second command to chmod the permissions before or after writing to it.

I am using GNU bash 4.2.25 and Ubuntu 12.04, if that makes a difference - general answers are preferred.

5

There's no way to do it while piping as far as I know, a simple script might be the best solution.

if [ -e /tmp/foo.log ]; then
    foo >> /tmp/foo.log
else
    foo >> /tmp/foo.log
    chmod 0644 /tmp/foo.log
fi
  • Thanks Slowki, that was my hunch as well. I'm going to leave it open for a few days, in the hopes of attracting a guru to enlighten us. – Patrick M Jan 21 '14 at 17:30
  • 3
    The problem with this approach is that it creates a short time window when the permissions on the file are wrong. I would not use it if the goal is to protect sensitive data. – proski Oct 14 '15 at 17:04
11

I know it's an old question, but I wanted to add my two cents.

I had the same idea and came up with a solution similar to BowlesCR. The problem with his solution was that my command (foo) wouldn't work if I changed the umask before running it, so this is my take on the problem:

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

Here, umask only affects the redirection to foo.log in the subshell. Everything else remains unaffected.

A bit convoluted, but it works.

  • Very nice and effective :) Just can't be used with stderr redirection on top of stdout redir. – Orsiris de Jong Apr 8 '17 at 19:28
2

Without true scripting, you can chain a bit:

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

Effectively similar to Slowki's answer, but condensed into a one-liner.

The only other thing I can think of is tinkering with the umask. Best to do this in a subshell so it doesn't pollute the current environment:

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

Two problems with that though.

  1. Umask can't raise the permissions above the level specified in the creat() syscall (0644 appears to be what Bash uses).
  2. This won't change the permissions on an existing file (because you're using the >> append operator).
  • I'm still new enough to *nix that the umask is still a bit of magic to me. Thanks for the tip, I'll be sure to read up on it. – Patrick M Jan 21 '14 at 19:13
  • Hmm … Still allows an unprivileged process from opening the file and later read its content. – Feuermurmel Apr 16 '17 at 11:28

Your Answer

By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.