-1

I am passing 2 parms to a bash script. The first parm is group and the second parm is the groupID. I want to write a bash script that will check if group is present in /etc/group or not. If not present, then the script should add group and gid to /etc/group. If present then it should match the gid with the 2nd param. If gid doesn't match the 2nd param then it should overwrite the gid with 2nd parm.

In short, group name and gid that I am passing to the script, should be in the /etc/group file.

I am running the command as:

./addgroup.sh groupa 123

suppose /etc/group has an entry:

groupa:x:345

After the running the command, when i browse /etc/group it should have value

groupa:x:123

I have written the following addgroup.sh so far:

if grep -q "^$1:" /etc/group
then
    echo "group $1 exists:SUCCESS"
else
    grep -q "^$1:" /etc/group || /bin/echo "$1:x:$2:" >> /etc/group
    cat /etc/group
    echo "group $1 added:SUCCESS"
fi
meallhour
  • 13,921
  • 21
  • 60
  • 117

2 Answers2

1

I believe that this code meets your needs and is simpler:

{ grep -v "^$1:" /etc/group; echo "$1:x:$2:"; } >/etc/group.tmp && mv /etc/group.tmp /etc/group

The question states that you would like to update the group ID even if the group already exists. The code here has that feature.

How it works:

  • grep -v "^$1:" /etc/group

    This removes the existing definition of group $1 if one exists.

  • echo "$1:x:$2:"

    This adds back a correct definition of group $1 with the correct group ID.

  • { ... } && mv /etc/group.tmp /etc/group

    If commands in braces executed successfully, this updates /etc/group.

Preserving existing group members

As sjnarv points out, one might want to preserve existing group members. In that case:

awk -v g="$1" -v id="$2" -F: -i inplace '$1 == g{save=$4; next} {print} ENDFILE{print g, "x", id, save}' OFS=: /etc/group

This requires GNU awk. (On Ubuntu, GNU awk is available but it is not usually the default.) For standard awk:

awk -v g="$1" -v id="$2" -F: '$1 == g{save=$4; next} {print} END{print g, "x", id, save}' OFS=: /etc/group > /etc/group.tmp && mv /etc/group.tmp /etc/group

How it works:

  • -v g="$1" -v id="$2"

    This uses shell variables $1 and $2 to define two awk variables g and id.

  • -F:

    This tells awk that our field separator is :.

  • -i inplace

    This tells awk to modify the file in-place (GNU awk only).

  • $1 == g{save=$4; next}

    If we encounter an existing definition of group g in the file, save the group members (the fourth field) in variable save and then skip the rest of the commands and jump to the next line.

    Here, inside the awk script, $1 and $4 are awk variables representing the first and fourth fields on the line. These variables are entirely separate and unrelated to the shell variables $ and $4 which would represent arguments to the shell script.

  • print

    For all other lines in /etc/group, we just print them as is.

  • ENDFILE{print g, "x", id, save}

    After reaching the end of /etc/group, we print the new definition of group g with group ID id and group members save. (For standard awk, we use END in place of ENDFILE.)

  • OFS=:

    This tells awk to use : as the field separator on output.

John1024
  • 109,961
  • 14
  • 137
  • 171
  • thanks. should it be `grep -v "^$1:" /etc/group` instead of `grep -v "^$1:" group` – meallhour Aug 29 '17 at 22:37
  • @meallhour Yes, that is correct. Answer updated with directories added. You may need to reload the page to see it. – John1024 Aug 29 '17 at 22:39
  • when running the command i get message `override rw-r--r-- root/wheel for /etc/group? (y/n [n]) ` – meallhour Aug 30 '17 at 20:42
  • @meallhour That message indicates that our command is being run by a member of the `wheel` group when it really should be run by `root`. When you see that message, try answering `y`. If that doesn't work, run the commands as user `root`. – John1024 Sep 04 '17 at 18:03
1

@John1024 has a nice answer for manual editing of the text file /etc/group, although I suspect it may have an issue not damaging a group that has members:

docker:x:1001:bob,alice

Also, most current systems have a pair of group-related files: /etc/group and /etc/gshadow.

If the task at hand is a real sysadmin one, consider using the tools already in place for managing the groups-related files: groupadd and groupmod.

Here's an attempt:

#!/usr/bin/env bash

if [[ $# -ne 2 ]]; then
  echo "Usage: $(basename $0) <groupname> <groupid>" 1>&2
  exit 1
fi

set -e

[[ $EUID -eq 0 ]] || exec sudo "$0" "$@"

type groupadd &> /dev/null || PATH=/sbin:/usr/sbin:"$PATH"

# Add the group if it's not already present
#
grep -q "^$1:" /etc/group || groupadd -g "$2" "$1"

# Edit the group if it does not have the desired gid
# (See groupmod(8) for implications of a gid change here -
#  note that it will *not* change files' group ownerships
#  out in the system.)
#
grep -q "^$1:[^:]*:$2:" /etc/group || groupmod -g "$2" "$1"

Edit: a simpler version with no check for running as root or attempt to use sudo, and a simpler interpreter line that assumes bash is available on /bin/bash on the system.

#!/bin/bash

if [[ $# -ne 2 ]]; then
  echo "Usage: $(basename $0) <groupname> <groupid>" 1>&2
  exit 1
fi

set -e

grep -q "^$1:" /etc/group || groupadd -g "$2" "$1"
grep -q "^$1:[^:]*:$2:" /etc/group || groupmod -g "$2" "$1"

If saved as groupedit.sh and made executable, run as root directly or via

$ sudo ./groupedit.sh

The groupadd/groupmod commands are the same, just without the comments of the first version.

sjnarv
  • 2,334
  • 16
  • 13
  • The script is taking too long to run. Can you please check on it? – meallhour Aug 29 '17 at 23:05
  • The script does run for me as I expect on a couple systems (CentOS7.3 and RHEL7.3 Linux). Save it as (for example) groupedit.sh, do `chmod 755 groupedit.sh`, and try running it as (again, for example) `./groupedit.sh newgroup 2345` - The `groupadd` and `groupmod` commands need to be run as root, hence the use of `sudo`, but if the `exec sudo` doesn't work for you, delete that line and use `sudo groupadd` and `sudo groupmod` instead. – sjnarv Aug 30 '17 at 13:02
  • I am getting message `/adduser.sh: fork: Resource temporarily unavailable` I have tried running it on various servers – meallhour Aug 30 '17 at 21:05
  • I am getting message /adduser.sh: fork: Resource temporarily unavailable I have tried running it on various servers – meallhour Aug 31 '17 at 14:34
  • Edited answer to offer a non-sudo-ing version of the approach - perhaps my use of sudo is an issue on your particular system/shell. The name of the script in your error messages suggests you might be trying to do more than just fiddle with groups ("adduser") - does it include additional commands my suggested answer does not? And if you're writing a script to add a user, in the spirit of this answer, do you know there's usually an administrative command on Unix-like systems to do that? On many Linuxes, its called `useradd`. – sjnarv Aug 31 '17 at 18:57