RHCSA Practice ExamLesson 2 of 4
Part A: Users, access and automation (100 points)
Seven tasks on accounts, sudo, password policy, shared directories, scheduling, a script, archives and time. Work on node1.
useraddchagesetfaclcrontabsystemctl list-timerstarfindgrepchronyc
After this lesson you can
- Complete the account, scheduling, scripting and text-processing tasks of the exam within about 55 minutes.
How to run Part A
Start the clock when you read A1. Work on node1. Everything you create must still be there after a reboot.
| Task | Topic | Points | Minutes | Skills it draws on |
|---|---|---|---|---|
| A1 | Users, groups, sudo | 18 | 10 | Users, Groups and sudo |
| A2 | Password policy, umask | 12 | 6 | Users, Groups and sudo; Shell Fluency |
| A3 | Shared directory | 12 | 6 | File Systems: permission problems |
| A4 | Cron, timer | 16 | 8 | Scheduling and Time |
| A5 | Script | 18 | 10 | Shell Scripting |
| A6 | Archive, find, grep | 14 | 8 | Archives; Working with Text |
| A7 | Time client | 10 | 5 | Scheduling and Time |
The tasks are independent apart from users (A1) being needed by A2, A3 and A4. If one task stalls for longer than 1.5 times its minutes, write down its number and move on.
A1 __/18 A2 __/12 A3 __/12 A4 __/16 A5 __/18 A6 __/14 A7 __/10 Part A = ___/100
Marking Part A
For each task run its checks, in a fresh shell, as the user named. Award the points only if every check passes. Record the result on the marking sheet from the briefing.
| Common reason for a lost point | Where it came from |
|---|---|
Crontab typed for root instead of natasha | A4: use crontab -u natasha |
| Timer started but not enabled, or the service enabled instead of the timer | A4 |
| Script not executable by others, or the usage message on stdout | A5 |
login.defs edited but the check expected only new users to be affected | A2: read what is asked |
sudo -l correct but file mode wrong, so visudo -c complains | A1 |
| Setgid missing, so files get the creator’s group | A3 |
chronyd restarted but not enabled | A7 |
Total available in Part A: 100 points. Write your score before starting Part B.
Practice
0 of 7 done
Do these on your own system. They get harder. Check each result, then tick it off.
- Practice
A1 · Users, groups and sudo (18 points, 10 min)
On node1:
- Create the group
devswith GID5500and the groupsysadm. - Create user
natashawith UID3456, primary groupdevsand supplementary groupsysadm. - Create user
harrywith supplementary groupsysadmand the default shell/bin/bash. - Create user
sarahwith the shell/sbin/nologin, not a member ofsysadm. - Set the password of all three users to
Ex200!Lab. - Members of
sysadmmust be able to run any command as root through sudo without being asked for a password.sarahmust not have sudo rights.
Check your result
id natashashowsuid=3456,gid=5500(devs), groups includingsysadm.id harrylistssysadm.getent passwd sarah | cut -d: -f7prints/sbin/nologin.getent group devsshows GID5500.sudo -l -U harryshows(ALL) NOPASSWD: ALL;sudo -l -U sarahsays she may not run sudo.sudo visudo -creports every file parsed OK.su - sarahis refused with the message that the account is unavailable.
Hint
groupadd -g 5500 devs,useradd -u 3456 -g devs -G sysadm natasha,chpasswd, and a drop-in file/etc/sudoers.d/sysadmwith%sysadm ALL=(ALL) NOPASSWD: ALL(check withvisudo -c, mode 440).Solution
sudo groupadd -g 5500 devs sudo groupadd sysadm sudo useradd -u 3456 -g devs -G sysadm natasha sudo useradd -G sysadm -s /bin/bash harry sudo useradd -s /sbin/nologin sarah for u in natasha harry sarah; do echo "$u:Ex200!Lab" | sudo chpasswd; done echo '%sysadm ALL=(ALL) NOPASSWD: ALL' | sudo tee /etc/sudoers.d/sysadm sudo chmod 440 /etc/sudoers.d/sysadm sudo visudo -c id natasha harry sarah - Create the group
- Practice
A2 · Password policy and default umask (12 points, 6 min)
On node1:
- Accounts created from now on must have passwords that expire after 45 days, may not be changed within 2 days of the last change, and warn 7 days before expiry.
natashamust change her password at least every 30 days, with a 5-day warning.harrymust be forced to change his password at his next login.sarah's account must expire on2027-12-31.- Files that
natashacreates in her login shell must have mode640and directories750by default.
Check your result
grep -E '^PASS_(MAX|MIN|WARN)' /etc/login.defsshowsPASS_MAX_DAYS 45,PASS_MIN_DAYS 2,PASS_WARN_AGE 7.chage -l natashashows maximum 30, warning 5.chage -l harryshowsLast password change: password must be changed.chage -l sarahshowsAccount expires: Dec 31, 2027.sudo -i -u natasha umaskprints0027.
Hint
/etc/login.defsaffects only users created afterwards.chage -M -W -d -Echange existing ones. A login shell reads~/.bash_profile, which sources~/.bashrc: putumask 027there.Solution
sudo sed -i -E 's/^PASS_MAX_DAYS.*/PASS_MAX_DAYS 45/; s/^PASS_MIN_DAYS.*/PASS_MIN_DAYS 2/; s/^PASS_WARN_AGE.*/PASS_WARN_AGE 7/' /etc/login.defs sudo chage -M 30 -W 5 natasha sudo chage -d 0 harry sudo chage -E 2027-12-31 sarah echo 'umask 027' | sudo tee -a /home/natasha/.bashrc sudo chown natasha:devs /home/natasha/.bashrc grep -E '^PASS_(MAX|MIN|WARN)' /etc/login.defs chage -l natasha | head -8 sudo -i -u natasha umask - Practice
A3 · Shared directory for the sysadm group (12 points, 6 min)
On node1 create
/srv/sysadm:- owned by
root, groupsysadm; - members of
sysadmcan create, read, modify and delete files in it; nobody else has any access; - every new file or directory created in it automatically belongs to group
sysadm; - a file created by
natashamust be writable byharrywithout anyone changing a mode by hand (regardless of their umask).
Check your result
ls -ld /srv/sysadmshowsdrwxrws---and groupsysadm.getfacl /srv/sysadmincludesdefault:group:sysadm:rwx.sudo -u natasha touch /srv/sysadm/a.txt && sudo -u harry bash -c 'echo ok >> /srv/sysadm/a.txt'succeeds.sudo -u sarah ls /srv/sysadmis denied.
Hint
Mode
2770gives setgid. A default ACL,setfacl -d -m g:sysadm:rwx, makes new files group-writable independent of umask. Note that natasha's umask is 027 from the previous task.Solution
sudo mkdir -p /srv/sysadm sudo chown root:sysadm /srv/sysadm sudo chmod 2770 /srv/sysadm sudo setfacl -d -m g:sysadm:rwx /srv/sysadm sudo setfacl -m g:sysadm:rwx /srv/sysadm ls -ld /srv/sysadm getfacl /srv/sysadm sudo -u natasha touch /srv/sysadm/a.txt sudo -u harry bash -c 'echo ok >> /srv/sysadm/a.txt' && echo harry-can-write - owned by
- Practice
A4 · Cron job and systemd timer (16 points, 8 min)
On node1:
- Schedule a cron job for
natashathat runslogger "EX200 in progress"at 14:23 every weekday (Monday to Friday). - Create a systemd service
report.servicethat runs/usr/local/bin/report.sh(you write it: it appends the output ofdateto/var/log/report.log), and a timerreport.timerthat runs it every day at 06:30 and runs it at the next boot if the machine was off at 06:30. The timer must be enabled and active.
Check your result
crontab -l -u natashashows23 14 * * 1-5 logger "EX200 in progress".systemctl is-enabled report.timerprintsenabled;systemctl is-active report.timerprintsactive.systemctl cat report.timershowsOnCalendar=--* 06:30:00andPersistent=true.sudo systemctl start report.service && tail -1 /var/log/report.logprints a date.
Hint
crontab -u natasha -e. The service isType=oneshot; the timer needs[Install] WantedBy=timers.target.daemon-reloadafter creating units. Enable the timer.Solution
( sudo crontab -u natasha -l 2>/dev/null; echo '23 14 * * 1-5 logger "EX200 in progress"' ) | sudo crontab -u natasha - sudo crontab -u natasha -l printf '#!/bin/bash\ndate >> /var/log/report.log\n' | sudo tee /usr/local/bin/report.sh sudo chmod 755 /usr/local/bin/report.sh sudo tee /etc/systemd/system/report.service <<'EOT' [Unit] Description=Daily report [Service] Type=oneshot ExecStart=/usr/local/bin/report.sh EOT sudo tee /etc/systemd/system/report.timer <<'EOT' [Unit] Description=Run the report daily [Timer] OnCalendar=*-*-* 06:30:00 Persistent=true [Install] WantedBy=timers.target EOT sudo systemctl daemon-reload sudo systemctl enable --now report.timer systemctl list-timers report.timer --no-pager - Schedule a cron job for
- Challenge
A5 · A shell script that takes arguments (18 points, 10 min)
On node1 create the executable script
/usr/local/bin/fileinfo.sh, usable by every user:- For each argument, print
ARGUMENT: directoryif it is a directory,ARGUMENT: file (N bytes)if it is a regular file (N is its size), orARGUMENT: missingotherwise. - The exit status is
0if everything exists and1if at least one argument is missing. - With no arguments it prints
Usage: SCRIPTNAME PATH...on standard error and exits with status2.
Check your result
fileinfo.sh /etc /etc/hostnameprints/etc: directoryand/etc/hostname: file (N bytes);echo $?is0.fileinfo.sh /etc /nopeprints amissingline;echo $?is1.fileinfo.sh 2>/dev/null; echo $?prints2; without the redirect the usage line is printed.ls -l /usr/local/bin/fileinfo.shshows-rwxr-xr-x.sudo -u sarah /usr/local/bin/fileinfo.sh /etcworks.
Hint
Test the argument count with
[ $# -eq 0 ], loop over"$@", use-dand-f,stat -c %s FILEfor size, and keep astatusvariable.Solution
sudo tee /usr/local/bin/fileinfo.sh <<'EOT' #!/bin/bash if [ $# -eq 0 ]; then echo "Usage: $0 PATH..." >&2 exit 2 fi status=0 for p in "$@"; do if [ -d "$p" ]; then echo "$p: directory" elif [ -f "$p" ]; then echo "$p: file ($(stat -c %s "$p") bytes)" else echo "$p: missing" status=1 fi done exit $status EOT sudo chmod 755 /usr/local/bin/fileinfo.sh fileinfo.sh /etc /etc/hostname /nope; echo $? fileinfo.sh; echo $? - For each argument, print
- Practice
A6 · Archives, find and grep (14 points, 8 min)
On node1, as root:
- Create
/root/ssh-backup.tar.bz2, a bzip2-compressed archive of the directory/etc/ssh. - Create the directory
/opt/restoreand extract onlyetc/ssh/sshd_configfrom that archive into it. - Write the paths of all regular files under
/usr/share/doclarger than 100 KiB, sorted alphabetically, one per line, to/root/bigdocs.txt. - Write every line of
/etc/servicesthat containsssh(any case) and is not a comment line to/root/ssh-lines.txt.
Check your result
file /root/ssh-backup.tar.bz2saysbzip2 compressed data;tar -tjf /root/ssh-backup.tar.bz2listsetc/ssh/sshd_config.find /opt/restore -type fprints only/opt/restore/etc/ssh/sshd_config./root/bigdocs.txtis non-empty, sorted (sort -c /root/bigdocs.txtprints nothing), every path exists and is over 100k./root/ssh-lines.txthas no line beginning with#and every line matchessshignoring case.
Hint
tar -cjf,tar -xjf ARCHIVE -C DIR MEMBER,find -type f -size +100k | sort,grep -i ssh FILE | grep -v '^#'. tar strips the leading/and warns; that is normal.Solution
sudo tar -cjf /root/ssh-backup.tar.bz2 /etc/ssh sudo mkdir -p /opt/restore sudo tar -xjf /root/ssh-backup.tar.bz2 -C /opt/restore etc/ssh/sshd_config sudo find /opt/restore -type f sudo find /usr/share/doc -type f -size +100k | sort | sudo tee /root/bigdocs.txt >/dev/null grep -i ssh /etc/services | grep -v '^#' | sudo tee /root/ssh-lines.txt >/dev/null sudo sort -c /root/bigdocs.txt && echo sorted - Create
- Warm-up
A7 · Time client and time zone (10 points, 5 min)
On node1 (node2 already serves time):
- Synchronise the clock with the server
node2.lab.exampleonly: remove or disable the default pool. - Make sure the time service starts at boot.
- Set the system time zone to
Asia/Riyadh.
Check your result
grep -E '^(server|pool)' /etc/chrony.confshowsserver node2.lab.example iburstand no activepoolline.systemctl is-enabled chronydisenabled,systemctl is-active chronydisactive.chronyc sourceslistsnode2.lab.example(after a minute it carries^*).timedatectl | grep 'Time zone'showsAsia/Riyadh.
Hint
Comment out the
poolline, addserver node2.lab.example iburst,systemctl restart chronyd,timedatectl set-timezone Asia/Riyadh.Solution
sudo sed -i 's/^pool /#pool /' /etc/chrony.conf echo 'server node2.lab.example iburst' | sudo tee -a /etc/chrony.conf sudo systemctl enable --now chronyd sudo systemctl restart chronyd sudo timedatectl set-timezone Asia/Riyadh sleep 5; chronyc sources timedatectl - Synchronise the clock with the server