Hello I try to write script to make this "If the file exists Must be owned by a system user and group. Permissions for other must be r-x or more restrictive."
Aix systems 7.2
#MODULE BODY
file_path="/bin/ssh-add"
if [ -e $file_path ];
then
user=`istat $file_path | grep Owner: | awk '{print $2}'`
uid=`id -u $user`
if [ $uid -lt 500 ];
then
permissions=`istat $file_path | grep Owner: | awk '{print $2}' `
if [ $permissions -le 755 ];
then
compliant="Yes"
actual_value='User = '$user', Permissions = '$permissions
else
compliant="No"
actual_value="Bad permissions"
fi;
else
compliant="No"
actual_value="Not system user"
fi;
else
compliant="Yes"
actual_value="NA"
fi;
# SCRIPT RESULT
echo :::$module_id:::$compliant:::$actual_value:::
echo " === End of $module_id module === "
I suggest to use find command with -perm options.
See documentation here.
With the following command you can verify the file has no write permission to others.
find $file_path -perm o-w
With the following command you can verify the file has no write permission to group.
find $file_path -perm g-w
With the following command you can verify the file has no write permission to group nor others.
find $file_path -perm go-w
Related
I'm trying to make a script that will find all symlinks in a directory that the script is currently in, and it will echo "This 'link' refers to 'path' and it's owner is 'owner'.
I've come up with this solution so far, but it doesn't work for some reason.
Here's my code:
#!/bin/bash
for each in .
do
echo "Link '$1' refers to" $(realpath $1) "and its owner is: " $(ls -ld $(realpath $1) | awk '{print $3}')
end for
And this it the error that it gives me:
jakub.kacerek#perun:~$ ./najdi_symlink.sh
./najdi_symlink.sh: line 7: syntax error: unexpected end of file
jakub.kacerek#perun:~$
I'm 100% sure that the error is in the for loop, but I don't know how to solve it.
Well after a quick thought I found out the solution for it, it may not be the smartest one but it gets the job done.
The solution is:
#!/bin/bash
for each in $(find . -maxdepth 1 -type l -ls | awk '{print $11}'); do
echo "Link '$each' refers to" $(realpath $each) "and its owner is: " $(ls -ld $(realpath $each) | awk '{print $3}')
done
Once you figured out you can use find, why do you keep using a for-loop?
find . -type l -exec echo {} : $(realpath {}) \;
This is not complete but it shows what you can do:
basic usage of find
find, combined with {} (find result)
You can launch commands (like realpath) on the find result.
Have fun :-)
I liked the assignment. I've figured it out.
I'm trying to make a script that will find all symlinks in a directory that the script is currently in, and it will echo "This 'link' refers to 'path' and it's owner is 'owner'.
You might need to change the strings, but the actual code works.
#!/bin/bash
for item in * ; do
if [ ! -L $item ]
then
echo "filename: '$item' is NOT a symlink"
else
printf "filename: '$item' is a symlink " && echo $item | awk '{printf("%s ->", $1); system("readlink -f " $1)}' && printf 'owner is: ' ; stat -c '%U' $item
fi
done
Example output:
[vagrant#vm-local-1 ~]$ ./a.sh
filename: 'a.sh' is NOT a symlink
filename: 'hi.jar' is NOT a symlink
filename: 'ho' is a symlink ho ->/tmp/abc/ho
owner is: vagrant
filename: 'one' is NOT a symlink
filename: 'test.jar' is NOT a symlink
filename: 'test.tar.gz' is NOT a symlink
filename: 'two' is a symlink two ->/home/vagrant/one
owner is: vagrant
I am trying to run a script that validates if all the tables that are supposed to be created as a part of my deployment. This is my script:
set -x
ENV=$1
. /user/setenv.sh
ticket=""
wlf_kinit ticket
echo "Checking if Kerberos Ticket is available.."
klist $ticket
if [ $? -eq 1 ]; then
echo "Kerberos Ticket not found..Exiting"
exit 1
fi
echo "Validating Hadoop tables" > /tmp/psk1/db_validation_log.txt
db_dir=/user/db
cd $db_dir
for current_directory in `find . -maxdepth 1 -type d`
do
#current_directory=`echo $current_directory | awk -F '/' '{print $2}'`
echo $current_directory
if [ "$current_directory" != "." ]; then
current_directory=`echo $current_directory | awk -F '/' '{print $2}'`
if [ "${current_directory:0:1}" = "v" ]; then
dir=$db_dir/$current_directory/views
else
dir=$db_dir/$current_directory/tables
fi
cd $dir
pwd
#echo "Validating tables in "$current_directory >> /tmp/psk1/db_validation_log.txt
find . -name '*.hql' | while read rec; do
echo $rec
tbl_name=`echo $rec | awk -F '/' '{print $2}' | awk -F '.' '{print $1}'`
result=$(impala-shell --quiet --delimited --ssl -i ${impala_host} -ku ${user_id}${impala_realm} -q "set request_pool = ${request_pool}; use $current_directory$ENV; invalidate metadata $tbl_name; show tables like '$tbl_name';") 2>> /tmp/psk1/db_validation_log.txt
#echo $result
if [ $? -eq 0 ]; then
if [ ${result} == ${tbl_name} ]; then
echo "$tbl_name exists" #>> /tmp/psk1/db_validation_log.txt
else
echo "$tbl_name does not exist" #>> /tmp/psk1/db_validation_log.txt
fi
else
echo $current_directory$ENV"."$tbl_name" Query error" >> /tmp/psk1/db_validation_log.txt
impala-shell --quiet --delimited --ssl -i ${impala_host} -ku ${user_id}${impala_realm} -q "set request_pool = ${request_pool}; use $current_directory$ENV; invalidate metadata $tbl_name; show tables like '$tbl_name';" 2>> /tmp/psk1/db_validation_log.txt
fi
done
fi
done
cat /tmp/psk1/db_validation_log.txt | mail -a /tmp/psk1/db_validation_log.txt -s 'Hadoop DB validation completed. Check the attached log.' -r ${from_email} ${to_email} 2>> /tmp/psk1/db_validation_log.txt
kdestroy -c $ticket
This script prints the failed queries to a .txt file and sends it in an email. In the text file I see some of the queries failing with TableNotFoundException. But when I open the impala shell and list out the tables, I am able to see the table in the list. I am not sure what is causing this inconsistency.
Any help would be appreciated. Thank you.
I am able to get both listings ( /etc/passwd and /home ) but how to script something like read line of /etc/passwd, parse home directory, then look for that in /home . If it doesn't exist, throw an error, if it does exist, move along.
/etc/passwd home dir listing for users
cut -d":" -f6 /etc/passwd | grep home | sort
user listing from /home
ls -1 /home | (while read line; do echo "/home/"$line; done)
Maybe right out output from first command to a file, then read each line into a find command and...or, test with
if [ -d "$DIRECTORY" ]; then
echo "directory found for user that doesn't exist"
fi
Now how to put it all together...
EDIT: isedev had exactly what I needed. I may have mis-worded my original message...we have been cleaning up users, but not cleaning up their /home directory. So I want to know what /home directories still exist that don't have /etc/passwd entries.
this is what worked to a T
for name in /home/*; do
if [ -d "$name" ]; then
cut -d':' -f6 /etc/passwd | egrep -q "^$name$"
if [ $? -ne 0 ]; then
echo "directory $name does not correspond to a valid user"
fi
fi
done
from now on, we will be running
userdel -r login
This will report all home directories from /etc/passwd that should be in /home but aren't:
cut -d":" -f6 /etc/passwd | grep home | sort |
while read dir; do [ -e "$dir" ] || echo Missing $dir; done
And this one reports all that don't exist:
cut -d":" -f6 /etc/passwd | while read dir; do
[ -e "$dir" ] || echo Missing $dir
done
as 1st approximation:
perl -F: -lane 'next if m/^#/;print "$F[5] for user $F[0] missing\n" unless(-d $F[5])' /etc/passwd
if you want find the differences between the /etc/passwd and the /home
comm <(find /home -type d -maxdepth 1 -mindepth 1 -print|sort) <(grep -v '^#' /etc/passwd | cut -d: -f6| grep '/home' | sort)
in an narrow form
comm <(
find /home -type d -maxdepth 1 -mindepth 1 -print |sort
) <(
grep -v '^#' /etc/passwd |cut -d: -f6 |grep /home |sort
)
if you will use
comm ... (without args as above) will show 3 colums 1.) only in /home 2.)only in /etc/passwd 3.) common
comm -23 .... - will show directories what are only in the /home (and not in the /etc/passwd)
comm -13 .... - will show dirs what are only in the /etc/passwd and not in the /home
comm -12 .... - will show correct directories (exists in the /etc/passwd and the /home too)
I'm not sure with the -{max|min}depth on the AIX..
So, assuming you want to know if there are directories under /home which do not correspond to existing users:
for name in /home/*; do
if [ -d "$name" ]; then
cut -d':' -f6 /etc/passwd | egrep -q "^$name$"
if [ $? -ne 0 ]; then
echo "directory $name does not correspond to a valid user"
fi
fi
done
Then again, this assumes you are not using a name service such as LDAP or NIS, in which case, change the line starting with cut to:
getent passwd | cut -d':' -f6 | egrep -q "^$name$"
After reading the man page of getfacl / setfacl I could not find an obvious/robust/elegant method to check whether acl is enabled for a given path in (ba)sh.
Any suggestions?
{
# Determine what the mount point for the path is:
MOUNT_POINT=$(df -P $FILENAME | tail -n 1 | awk '{print $6}')
# Get the mount options for the path:
MOUNT_OPTS=$(awk '$2=="'$MOUNT_POINT'" { print $4 }' /proc/mounts)
# Check to see if acl is one of the mount points:
echo $MOUNT_OPTS | tr , \\\n | grep '^acl$' -q
if [ $? -eq 0 ]; then
echo "ACLs enabled"
else
echo "ACLs disabled"
fi
}
I have homework (Shell script) which I tried my best to make it work, but in vain.
Can anyone help?
Question:
Write a bash program named fix-permissions.sh that accepts a list of users as arguments.
If one user or more are given as arguments, the script should reset file permissions as follows:
a. Directory ~/share to 750 (if it exists).
b. All regular files inside ~/share to 744.
c. All directories inside ~/share to 750.
d. All other regular files in ~ to 600 and all other directories in ~ to 700.
e. files of other types are left as they are.
We assume that there is only one level of files and directories inside ~ (except for ~/share), and there is only one level of files and directories inside ~/share.
If no arguments are given, the script should identify normal users in the system (UID >= 500) and for each user, reset files permissions as described above.
At the end of execution, this script must generate a file named report.txt that contains a list of all files in the user's home directory including full path, owner, group and permissions for each file.
What I have now looks like this:
[...and there is nothing...back to the revision history - this is from Revision 4...]
Part 1
#!/bin/bash
#$ fx-permiss.sh user1 user2 user3
for user ; do
if -d /home/$user/share ; then
chmod 750 /home/$user/share ; else
echo “No folder named “share” is in $user home directory”
fi
find /home/$user/share -type f -exec chmod 744 {} \;
find /home/$user/share -type d -exec chmod 750 {} \;
find ~ -type f -not \( -name share -o -name ~ \) -exec chmod 600
find ~ -type d -not \( -name share -o -name ~ \) -exec chmod 700
done
Part 2
If no arguments are give, the script should identify normal users in the system (UID >= 500) and for each user, reset files permissions as described above.
for User in $(cat /etc/passwd) ; do
UserId=$(echo $User | cut -d ":" -f 3)
if ($UserId -gt 500) ; then
# reset permission
fi
done
Part 3
At end of execution, produce a file named report.txt that contains a list of all files in the user's home directory including full path, owner, group and permissions for each file.
find . -ls | awk '{print $user1 "\t" $5 "\t" $6 "\t" $user}' | tee report.txt
#it should be for all users
#where it should be saved?
chmod 755 fix-permissions
exit 0
code from the initial post seems to have disappeared... rolled up an example.
#!/bin/bash
function mod {
if [ -d "/Users/$1/share" ]; then
echo "permissions changes for $1"
#chmod 750 /Users/$1/share
#find /Users/$1/share -type f -exec chmod 744 {} \;
#find /Users/$1/share -type d -exec chmod 750 {} \;
#find /Users/$1/ -type f -exec chmod 600 {} \;
#find /Users/$1/ -type d -exec chmod 700 {} \;
fi
}
function clean {
IFS=':' read -ra pw <<< "$1"
local c=0
local n=""
local t=500
for i in "${pw[#]}"; do
if [ $c == 0 ]; then
n="$i"
fi
if [ $c == 2 ]; then
if [ "$i" -gt "$t" ]; then
mod $n
fi
fi
c=$[$c+1]
done
}
function report {
export user=$(whoami)
ls -la "/Users/$user" > report.txt
}
if [ -z $1 ]; then"
while read line; do
if [ "${line:0:1}" != "#" ]; then
clean $line
fi
done < /etc/passwd
else
for arg in "$#"
do
mod $arg
done
fi
report
only requirement that it doesn't meet is printing full path (only prints relative) under #3 in the report. the variable t is the lowest uid the permissions changes will affect. commented out the chmods so no one accidentally does this to their system. oops.
Instead of specifying $1 $2 $3, loop over the inputs like so:
for user ; do
Then, you will need to change all $1 to $user