How to set specific file permissions when redirecting output?
Solution 1
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
Solution 2
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.
Solution 3
Without true scripting, you can chain a bit:
touch /tmp/foo.log; chmod 0644 /tmp/foo.log; foo >> /tmp/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 >> /tmp/foo.log)
Two issues with that, though.
- Umask can't raise the permissions above the level specified in the
creat()
syscall (0666 appears to be what Bash uses). - This won't change the permissions on an existing file (because
umask
applies only to file creation).
Solution 4
When the redirection sets the wrong permissions, e.g.:
$ 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
I believe you can use something like xynomorf gave, and address the stderr concern from Orsiris de Jong with a slight modification to use the bash process substitution.
$ 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
Naturally, use umask 0077
to get mode 600
and prohibit any other users from seeing the contents.
Comments
-
Patrick M over 1 year
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 wantfoo.log
to end up with. Most commands I've experimented with in bash end up interpreting0644
as an additional argument tofoo
.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.
-
Patrick M over 10 yearsThanks 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 over 10 yearsI'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.
-
proski over 8 yearsThe 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.
-
Orsiris de Jong about 7 yearsVery nice and effective :) Just can't be used with stderr redirection on top of stdout redir.
-
Feuermurmel about 7 yearsHmm … Still allows an unprivileged process from opening the file and later read its content.
-
Scott - Слава Україні almost 5 yearsThis answer works, as far as it goes, but @proski is right: the
umask
answers are better, and one of them should be accepted. -
Scott - Слава Україні almost 5 years
-
Scott - Слава Україні almost 5 years(Cont’d) … and this.) And the question specifically mentions mode 0644. So a
umask
value of 22, 23 or 32 would work as well, in this context (you don’t need to use leading zero(s); when modes andumask
values are specified numerically, they are always interpreted as octal).22
is more commonly, conventionally used. -
Scott - Слава Україні almost 5 years@Feuermurmel: So what? The question explicitly calls for mode 644. We have to assume that the OP knows that 644 means world-readable and intended to make his information public.
-
Feuermurmel almost 5 years@Scott I wrote that comment a long time ago. I have no idea why I mentioned that. Maybe I was thinking of write access instead …