Locked for 2 days. There are disputes about this question’s content being resolved at this time. It is not currently accepting new answers or interactions.
How do you test permissions on files using bash ? And how does it work ? Does it look for owner's permissions only or all of them (owner, group, others) ? I used -r and -w to test permissions on some files but I got some inaccurate responses.
Here is what I did :
[root#server1 ~]# cat script.sh
#!/bin/bash
FILE="$1"
[ $# -eq 0 ] && exit 1
if [[ -r "$FILE" && -w "$FILE" ]]
then
echo "We can read and write the $FILE"
else
echo "Access denied"
fi
[root#server1 ~]# ll file*
-rw-r--r--. 2 root root 1152 Jun 2 18:24 file1
-rwx------. 1 root root 3 Jun 6 20:35 file2
-r--------. 1 root root 3 Jun 6 20:35 file3
--w-------. 1 root root 3 Jun 6 20:35 file4
---x------. 1 root root 3 Jun 6 20:35 file5
----------. 1 root root 3 Jun 6 20:35 file6
[root#server1 ~]#
[root#server1 ~]# ./script.sh file1
We can read and write the file1
[root#server1 ~]# ./script.sh file2
We can read and write the file2
[root#server1 ~]# ./script.sh file3
We can read and write the file3
[root#server1 ~]# ./script.sh file4
We can read and write the file4
[root#server1 ~]# ./script.sh file5
We can read and write the file5
[root#server1 ~]# ./script.sh file6
We can read and write the file6
Thanks
There is nothing essentially wrong with your script. You are executing it as root so you do have permission to read and write, in fact, root has permission to do anything!
Check this post and you will see that even suppressing the permissions, root user can have access to them. Your output is correct. If you look into the man page of the test command, you can see that the -r and -w flags test if the file exist and in addition permissions to read and write respectively are granted to the user executing the command (both of them since you use a logical and).
Related
From a main bash script run as root, I want to execute a subprocess using sudo as unpriviledge user nobody; that subprocess should source a file, which content is provided by the main script.
I am trying to solve this using bash process substitution. But I cannot manage to get this to work.
Can someone tell me why the following script, ...
#! /bin/bash
sudo -u nobody \
bash -c 'source /dev/stdin || ls -l /dev/stdin /proc/self/fd/0 /proc/$$/fd/0; echo "A=$A"' \
< <(echo "A=$(ls /root/.profile)")
... when run as root, produces the following ouput ?
root#raspi:~# ./test3.sh
bash: line 1: /dev/stdin: Permission denied
lrwxrwxrwx 1 root root 15 Mar 20 20:55 /dev/stdin -> /proc/self/fd/0
lr-x------ 1 nobody nogroup 64 Aug 21 14:38 /proc/3243/fd/0 -> 'pipe:[79069]'
lr-x------ 1 nobody nogroup 64 Aug 21 14:38 /proc/self/fd/0 -> 'pipe:[79069]'
A=
I would expect reading from stdin to work because, as indicated by ls -l, read access to stdin is granted to nobody (which makes sense).
So why this does not work ? And is there any way to get this to work ?
Answers to this question did not help: as sample above shows, code in the <(...) bloc should access data that only root can.
To see why you have Permission denied, use ls -lL
sudo -u nobody \
bash -c 'source /dev/stdin || ls -lL /dev/stdin /proc/self/fd/0 /proc/$$/fd/0; echo "A=$A"' \
< <(echo "A=$(ls /root/.profile)")
To get around the error, use cat |
sudo -u nobody \
bash -c 'cat | { source /dev/stdin || ls -lL /dev/stdin /proc/self/fd/0 /proc/$$/fd/0; echo "A=$A"; }' \
< <(echo "A=$(ls /root/.profile)")
When I issued two equivalent commands in Bash I got different output (from "wc -l" command), see below:
root#devel:~# ls /usr/bin -lha | tee >(wc -l) >(head) > /dev/null
total 76M
drwxr-xr-x 2 root root 20K Nov 11 18:58 .
drwxr-xr-x 10 root root 4.0K Oct 8 15:31 ..
-rwxr-xr-x 1 root root 51K Feb 22 2017 [
-rwxr-xr-x 1 root root 96 Jan 19 2017 2to3-3.5
-rwxr-xr-x 1 root root 23K Mar 22 2017 addpart
lrwxrwxrwx 1 root root 26 May 10 2017 addr2line -> x86_64-linux-gnu- addr2line
lrwxrwxrwx 1 root root 6 Dec 13 2016 apropos -> whatis
-rwxr-xr-x 1 root root 15K Sep 13 19:47 apt
-rwxr-xr-x 1 root root 79K Sep 13 19:47 apt-cache
137
root#devel:~# ls /usr/bin -lha | wc -l
648
what am I missing?
it's strange, but when I call it this way it gets even stranger output:
root#devel:~# ls /usr/bin -lha | tee >(wc) >(wc) > /dev/null
648 6121 39179
648 6121 39179
root#devel:~# ls /usr/bin -lha | tee >(wc) >(wc) > /dev/null
648 6121 39179
648 6121 39179
root#devel:~# ls /usr/bin -lha | tee >(wc) >(wc -l) > /dev/null
648
root#devel:~# 648 6121 39179
seems like commands running asynchronously and ends in different time... or what it can be?
Simple answer:
how to fix:
ls /usr/bin -lha | tee --output-error=exit-nopipe >(wc -l) >(head) > /dev/null
Details:
The command head only prints the head of input, so it can finish its job as long as it gets enough input, then exits without waiting for all input.
So let's replace command head with the simple "head".
ls /usr/bin -lha | tee >(wc -l) >(read l; echo $l) > /dev/null
The simple "head" will read only one line, then exit, which causes that the pipe file gets closed immediately before tee finishes transferring all data to it.
So no doubt, you'll get same result with the simple "head". wc still prints wrong number.
The root reason of your issue, I think you can conclude yourself, is that one of the output pipes of tee is closed earlier, tee hits a write error, and then stops writing to other output files.
After understanding the root reason, I think it would be very easy for you to understand the following section in man page.
MODE determines behavior with write errors on the outputs:
'warn' diagnose errors writing to any output
'warn-nopipe'
diagnose errors writing to any output not a pipe
'exit' exit on error writing to any output
'exit-nopipe'
exit on error writing to any output not a pipe
The default MODE for the -p option is 'warn-nopipe'. The default operation
when --output-error is not specified, is to exit immediately on error writing to
a pipe, and diagnose errors writing to non pipe outputs.
Some extra words
Actually if you replace >(wc -l) with a regular file in your problematic command line, you will find the file size will always be 16384 or 20480 or 32768 or 36864 or 28672 or ..., all of which are the multiple of 4096. (The writing to the regular file is incomplete because tee aborts earlier. If the writing was complete, the file size would be any value.)
4096 is the value of PIPE_BUF for most UNIX-like system. If you know what PIPE_BUF is, you will easily understand why the file size is always the multiple of 4096.
I tried mimicking the behaviour of /dev/null in another location, but some strange error occurs. I learned how to generate a special file similar to /dev/null in -bash: /dev/null: Permission denied.
When in some folder, e.g. home, the following occurs:
$ sudo mknod -m 666 null2 c 1 3
$ cat null2
cat: null2: Permission denied
On the other hand, when in /dev, no error occurs:
$ cd /dev
$ sudo mknod -m 666 null2 c 1 3
$ cat null2
I can reproduce the error on another xubuntu machine, but on a third machine the error does not occur. Any clue whats going on there?
Strangely, on any of these machines, permissions and major/minor are identical:
$ ls -la null2
crw-rw-rw- 1 root root 1, 3 Mär 4 17:42 null2
$ ls -la /dev/null
crw-rw-rw- 1 root root 1, 3 Mär 4 11:46 /dev/null
Also same when copying /dev/null
$ sudo cp -pR /dev/null null2 && cat null2
cat: null2: Permission denied
Is the nodev mount option set for the file system containing your home directory?
Specifying nodev forces the file system to not interpret block special devices (like the null2 special file you create with mknod).
I have two shell scripts .
(working one)
$ cat script_nas.sh
#!/bin/bash
for i in `cat nas_filers`
do echo $i
touch /mnt/config-backup/nas_backup/$i.auditlog.0.$(date '+%Y%m%d')
ssh -o ConnectTimeout=5 root#$i rdfile /etc/configs/config_saved > /mnt/config-backup/nas_backup/$i.auditlog.0.$(date '+%Y%m%d')
done
other
(not working one)
$ cat script_san.sh
#!/bin/bash
for i in `cat san_filers`
do echo $i
touch /mnt/config-backup/san_backup/$i.auditlog.0.$(date '+%Y%m%d')
ssh -o ConnectTimeout=5 root#$i rdfile /etc/configs/config_saved > /mnt/config-backup/san_backup/$i.auditlog.0.$(date '+%Y%m%d')
done
Cron entries are:
$ crontab -l
Filers config save script
0 0 * * * /mnt/config-backup/script_san.sh
0 0 * * * /mnt/config-backup/script_nas.sh
0 0 * * * /mnt/config-backup/delete_file
Script script_san.sh is not working.
Outputs are like
SAN backup directory
san_backup]# ls -lart alln01-na-exch01a.cisco.com.auditlog*
-rw-r--r-- 1 root root 210083 Mar 1 22:24 alln01-na-exch01a.auditlog.0.20150301
[root#XXXXX san_backup]# pwd
/mnt/config-backup/san_backup
NAS backup directory
nas_backup]# ls -lart rcdn9-25f-filer43b.cisco.com.auditlog*
-rw-r--r-- 1 root root 278730 Feb 26 00:06 rcdn9-25f-filer43b.cisco.com.auditlog.0.20150226
-rw-r--r-- 1 root root 281612 Feb 27 00:17 rcdn9-25f-filer43b.cisco.com.auditlog.0.20150227
-rw-r--r-- 1 root root 284105 Feb 28 00:02 rcdn9-25f-filer43b.cisco.com.auditlog.0.20150228
-rw-r--r-- 1 root root 284101 Mar 1 00:02 rcdn9-25f-filer43b.cisco.com.auditlog.0.20150301
[root#XXXXXXX nas_backup]#
From cron logs I can see that cron is executing both the script but output for script_san.sh is not coming.
From my experience, most of the times script is working manually but not from crontab is because login scripts were not running. Try to add something like source ~/.bash_profile in the begging of script or first line in cron file. Did you try (for debugging) to run the script with at command?
I have this script which I can't execute:
#!/bin/bash
USERS="/etc/passwd"
for user in `$USERS | cut -f 1 -d ':'`
do
echo $user
done
This is the output of ls -l script.sh:
-rwxrwxrwx 1 user user 94 Jul 30 21:24 script.sh
What am I doing wrong? :|
I also tried running it as root and with sudo and nothing worked...it's annoying...
You're trying to execute /etc/passwd and send the output to cut. You want to redirect the contents of the file:
for user in `cut -f 1 -d : < $USERS`