Need help with this script


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting Need help with this script
# 1  
Old 07-03-2008
Need help with this script

Hi,
I'm new to unix shell scripting so I need some help here. I've been asked to create a script for work that will synchronize the user ids and group ids in the /etc/passwd and /etc/group files with other machines. I know that this is playing with fire a little but it is still required. When I run the following script without sudo then it doesn't execute the -add and -mod commands, but when I run it with sudo (i.e. sudo ./script) then I get the following errors:

[: 30: ==: unexpected operator
./script: 30: groupnum++: not found

for the first loop and

[: 63: ==: unexpected operator
./script: 63: usernum++: not found

for the second loop.

I would NOT suggest running the following script (though I don't think it can do any harm if you use your current passwd and group files as input and input2), but if anyone could point out any errors or offer any ideas it would be greatly appreciated. input and input2 are hypothetically the passwd and group files copied from another machine:


Code:
 # Make backups of the files
cp /etc/passwd backuppasswd
cp /etc/group backupgroup
# Variables for the 2 input files
inputpasswd=input
inputgroup=input2
awk -F: '{print $1}' $inputgroup > groupnames
awk -F: '{print $3}' $inputgroup > groupids
groupnum=1
# Add and update groups
while read groupline; do
    echo "$groupline"
    othergroupid=`sed -n "$groupnum{p;g;}" groupids`
    groupid=`awk -F: '$1=="'"$groupline"'" {print $3}' /etc/group`
    if [ "$groupid" == "" ]; then
        echo "Need to Add Group"
        groupadd -g $otherid $groupline
    fi
    ((groupnum++));
    if [ "$groupid" != "$othergroupid" ]; then
        echo "Group ID Mismatch"
        groupmod -g $othergroupid $groupline
    fi
#    echo Changing Group File and Directory Ownership
#    find / -group $groupid | xargs chgrp $othergroupid
done < groupnames
awk -F: '{print $1}' $inputpasswd > usernames
awk -F: '{print $3}' $inputpasswd > ids
awk -F: '{print $4}' $inputpasswd > groups
awk -F: '{print $5}' $inputpasswd > descriptions
usernum=1
#Add and update users
while read userline; do
    echo "$userline"
    otherid=`sed -n "$usernum{p;g;}" ids`
    othergroup=`sed -n "$usernum{p;g;}" groups`
    id=`awk -F: '$1=="'"$userline"'" {print $3}' /etc/passwd`
    group=`awk -F: '$1=="'"$userline"'" {print $4}' /etc/passwd`
    description=`sed -n "$usernum{p;g;}" descriptions`

    echo "$description"
    if [ "$id" == "" ]; then
        echo "Need to Add User"
        useradd -g $othergroup -c $description -u $otherid $userline
    fi
    ((usernum++));

    if [ "$id" != "$otherid" ]; then
        echo "ID Mismatch"
        usermod -u $otherid $userline
    fi
#    echo "Changing User File and Directory Ownership"
#    find / -user $id | xargs chown $otherid
#    echo "Changing Group File and Directory Ownership"
#    find / -user $id | xargs chgrp $othergroup
    if [ "$group" != "$othergroup" ]; then
        echo "Change User Primary Group"
        usermod -g $othergroup $userline
    fi
    echo
done < usernames
grouplist=`awk -F: '{print $1}' $inputgroup`
#Add users to their appropriate groups
for x in ${grouplist}; do
    #Use awk to get the actual comma separated list of users for each group
    userlist=`awk -F: '$1=="'"${x}"'" {print $4}' $inputgroup`
    arrayuserlist=`echo $userlist | tr ',' ' '`
    for y in ${arrayuserlist}; do
        echo "Adding to Group"
        echo "${x} ${y}"
        usermod -a -G ${x} ${y}
    done
done
#that section needs some rework so it gets the groups from imported file
rm ./groupnames
rm ./groupids
rm ./usernames
rm ./ids
rm ./groups
rm ./descriptions

# 2  
Old 07-03-2008
The ((usernum++)) syntax is not supported by all shells, so add a shebang line (e.g. #!/usr/bin/bash) to the beginning of the script to ensure it runs under the required shell when using sudo.
# 3  
Old 07-04-2008
MySQL

Great, that worked, thanks a bunch!
# 4  
Old 07-04-2008
Especially because you say yourself that you are "new to unix shell scripting" i will tell you the following - because you are new you have no habits which you would have to change and developing good habits is not more work than developing bad ones:

Do not use backticks, like in "var=`some_command`". Backticks are only included in modern shells for compatibility reasons. They are hard to read and easily overseen or misread. Furthermore backticks cannot be nested.

The modern replacement is "$(...)", which you can treat like a variable. It will - quite like the backtick construction - open a subshell, execute the commands and close the subshell again. The output will be in the "variables content".

Example:

Code:
myvar="$(echo "abcde" | tr '[a-z]' '[A-Z]')"
echo $myvar      # would yield "ABCDE"

This construct could also be nested and you can even use it in further constructs without having to assign it to a variable:

Code:
if [ $(command $myvars ; echo $?) -gt 0 ] ; then
     echo "ERROR: command had a nonzero return code"
else
     echo "Everything ok, command has returned 0
fi

Another thing is: you can use the shells string manipulating capabilities instead of relying on tools like awk or sed. Reading a file formatted like /etc/passwd (line=records, field separator=":") could be done the following way: we set the special shell variable "IFS" (the Internal Field Separator) to ":" for this operation (per default it is a space char) and then read several variables in one pass:

Code:
IFS=':'
cat /etc/passwd | while read Name junk UID PGrp Gecos junk ; do
     echo "------------------------"
     echo "User.........: $Name"
     echo "UID..........: $UID"
     echo "primary group: $PGrp"
     echo "Gecos........: $Gecos"
done

As you see you can even skip several fields this way - simply use a variable you do not use.

Save for that your script is very well written - even more so taking into account that you just started. Keep up the good work.

bakunin
Login or Register to Ask a Question

Previous Thread | Next Thread

5 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

How to block first bash script until second bash script script launches web server/site?

I'm new to utilities like socat and netcat and I'm not clear if they will do what I need. I have a "compileDeployStartWebServer.sh" script and a "StartBrowser.sh" script that are started by emacs/elisp at the same time in two different processes. I'm using Cygwin bash on Windows 10. My... (3 Replies)
Discussion started by: siegfried
3 Replies

2. Shell Programming and Scripting

Shell script works fine as a standalone script but not as part of a bigger script

Hello all, I am facing a weird issue while executing a code below - #!/bin/bash cd /wload/baot/home/baotasa0/sandboxes_finance/ext_ukba_bde/pset sh UKBA_publish.sh UKBA 28082015 3 if then echo "Param file conversion for all the areas are completed, please check in your home directory"... (2 Replies)
Discussion started by: ektubbe
2 Replies

3. UNIX for Dummies Questions & Answers

Calling a script from master script to get value from called script

I am trying to call a script(callingscript.sh) from a master script(masterscript.sh) to get string type value from calling script to master script. I have used scripts mentioned below. #masterscript.sh ./callingscript.sh echo $fileExist #callingscript.sh echo "The script is called"... (2 Replies)
Discussion started by: Raj Roy
2 Replies

4. Shell Programming and Scripting

Script will keep checking running status of another script and also restart called script at night

I am using blow script :-- #!/bin/bash FIND=$(ps -elf | grep "snmp_trap.sh" | grep -v grep) #check snmp_trap.sh is running or not if then # echo "process found" exit 0; else echo "process not found" exec /home/Ketan_r /snmp_trap.sh 2>&1 & disown -h ... (1 Reply)
Discussion started by: ketanraut
1 Replies

5. Shell Programming and Scripting

create a shell script that calls another script and and an awk script

Hi guys I have a shell script that executes sql statemets and sends the output to a file.the script takes in parameters executes sql and sends the result to an output file. #!/bin/sh echo " $2 $3 $4 $5 $6 $7 isql -w400 -U$2 -S$5 -P$3 << xxx use $4 go print"**Changes to the table... (0 Replies)
Discussion started by: magikminox
0 Replies
Login or Register to Ask a Question