Task
The system service apache2 is failing to start.
First, troubleshoot the failure and fix it.
Finally, start the systemd service and ensure it is running.
The Answer Is:
See the complete solution in Explanation.
Explanation:
Step 1: Connect to the correct Linux server.
The video specifies that this task must be performed on host lfcs00101a.
From the candidate terminal, execute:
ssh lfcs00101a
This establishes an SSH session with the server where the Apache service is failing.
All subsequent troubleshooting, configuration changes, and service operations must be performed on this host.
Step 2: Check the current status of the Apache service.
Execute:
sudo systemctl status apache2
This is the primary systemd command for checking the status of Apache.
It displays information such as:
Whether the apache2 service is loaded.
Whether the service is running, inactive or failed.
The process ID and execution status.
Recent service log messages.
Errors reported during startup.
An illustrative failure might appear as follows:
× apache2.service - The Apache HTTP Server
Loaded: loaded (/lib/systemd/system/apache2.service; enabled)
Active: failed (Result: exit-code)
Process: 1234 ExecStart=/usr/sbin/apachectl start
Main PID: 1234 (code=exited, status=1/FAILURE)
This is an example, not an output confirmed from the supplied video.
The Active: failed status means the service was unable to complete startup successfully.
Use the actual error messages to determine the cause.
Step 3: Examine the Apache service logs.
Execute:
sudo journalctl -u apache2 -b --no-pager
journalctl displays logs collected by systemd.
-u apache2 filters messages associated with the Apache service.
-b restricts results to the current boot.
--no-pager prints output directly without opening an interactive pager.
To display only the latest 50 messages:
sudo journalctl -u apache2 -n 50 --no-pager
These logs help identify why Apache failed.
Possible causes include:
Incorrect permissions on the Apache executable.
Invalid configuration directives.
Missing configuration files.
Another process using the required network port.
Inaccessible log directories.
Missing modules or other dependencies.
The official systemd documentation supports using journalctl -u to investigate the logs associated with a particular service.
Freedesktop
Step 4: Check the Apache executable.
On Ubuntu, the Apache server executable is normally located at:
/usr/sbin/apache2
Verify its existence:
ls -l /usr/sbin/apache2
For a more detailed permissions check:
stat -c '%A %a %U:%G %n' /usr/sbin/apache2
A correctly installed executable would typically have permissions similar to:
-rwxr-xr-x 755 root:root /usr/sbin/apache2
The x characters represent execute permission.
For example, if the permissions were incorrectly changed to:
-rw-r--r--
the executable would lack execution permission.
This can prevent Apache from starting successfully.
Step 5: Inspect the complete path permissions.
Execute:
namei -l /usr/sbin/apache2
This examines the permission bits and ownership of each directory component leading to the executable.
It helps distinguish between:
A non-executable Apache binary.
A directory that lacks search permission.
Incorrect ownership or permissions elsewhere in the path.
Also verify which package owns the executable:
dpkg -S /usr/sbin/apache2
On Ubuntu, it normally belongs to the apache2-bin package.
If required, check package-file integrity:
sudo dpkg -V apache2-bin
Package verification can help identify unexpectedly modified permissions or file contents.
Step 6: Correct the executable permission if it is the source of the failure.
In the supplied video, the candidate executes:
sudo chmod +x /usr/sbin/apache2
This is an important observation.
The command adds execute permission to the Apache executable according to the applicable chmod rules.
However, the candidate does not visibly demonstrate the earlier diagnostic output proving that missing execute permission caused the failure.
If the executable genuinely lacks its required execute permission, restore its expected mode:
sudo chmod 755 /usr/sbin/apache2
chmod changes file permissions.
755 grants read, write and execute permissions to the owner.
755 grants read and execute permissions to the group.
755 grants read and execute permissions to other users.
This is appropriate for a standard root-owned Apache executable when its mode has been incorrectly changed.
Do not execute this as a universal fix if the actual failure is a configuration error or port conflict.
Step 7: Verify the corrected permissions.
Execute:
ls -l /usr/sbin/apache2
Expected permissions, assuming the standard installation:
-rwxr-xr-x
For numerical verification:
stat -c '%a %n' /usr/sbin/apache2
Expected:
755 /usr/sbin/apache2
If the file's ownership is also incorrect, compare it with the package's expected ownership before making additional changes.
Step 8: Check the Apache configuration syntax.
Execute:
sudo apache2ctl configtest
This checks the Apache configuration for syntax errors.
For a valid configuration, the expected output is:
Syntax OK
The Apache control utility supports the configtest operation specifically for validating configuration syntax.
Apache HTTP Server Version 2.4
If it reports an error, inspect the identified file and line.
For example, an illustrative error might be:
Syntax error on line 42 of /etc/apache2/apache2.conf
Invalid command 'InvalidDirective'
In that case, correct the configuration directive instead of modifying executable permissions.
A successful syntax check does not guarantee that Apache can start, but it eliminates many configuration-related problems.
Step 9: Check whether Apache's required network ports are available.
Apache commonly listens on TCP port 80 for HTTP and port 443 for HTTPS.
Execute:
sudo ss -ltnp
To examine those ports specifically:
sudo ss -ltnp | grep -E ':(80|443)\b'
If another service already occupies a port configured for Apache, startup may fail with an address-binding error.
The official Apache documentation identifies port-binding conflicts as a common startup failure.
Apache HTTP Server Version 2.4
Do not stop another service unless the diagnostic evidence establishes that it is the source of the problem and the change is appropriate.
Step 10: Check Apache's own error log if necessary.
Execute:
sudo tail -n 50 /var/log/apache2/error.log
This displays recent entries from the standard Ubuntu Apache error log.
The file may contain additional details not included in the systemd journal.
Look for permission errors, configuration failures, missing resources or binding errors.
If the executable-permission repair was the only required correction, there may be no additional configuration changes to make.
Step 11: Start the Apache service.
After correcting the identified problem, execute:
sudo systemctl start apache2
sudo provides administrative privileges.
systemctl manages systemd services.
start requests that the specified service begin running.
apache2 identifies the Apache service unit.
This command directly satisfies the task's instruction to start the systemd service.
In the video, the candidate uses:
sudo systemctl restart apache2
The restart operation stops and starts an active service or starts it when appropriate.
Either operation can result in Apache running, but systemctl start apache2 is the more direct choice when the service is currently stopped or failed.
Step 12: Verify that Apache is running.
Execute:
sudo systemctl status apache2
Expected successful status:
● apache2.service - The Apache HTTP Server
Loaded: loaded
Active: active (running)
The critical field is:
Active: active (running)
This indicates that systemd considers the service active.
The official systemctl documentation defines the status command as the way to inspect the current runtime state of a service unit.
Linux manual page
Step 13: Verify the active service state directly.
Execute:
systemctl is-active apache2
Expected output:
active
Check the exit status immediately afterward:
echo $?
Expected:
0
The service is considered active when systemctl is-active returns active with a successful exit status.
Step 14: Verify that Apache is listening for connections.
Execute:
sudo ss -ltnp | grep apache2
This should display Apache processes listening on the ports specified in its configuration, provided those sockets can be associated with the process in the command output.
Alternatively, check the configured HTTP port:
sudo ss -ltnp | grep ':80'
An illustrative successful result might include:
LISTEN 0 511 0.0.0.0:80 0.0.0.0:*
The actual listening address and ports depend on Apache's configuration.
Step 15: Test the Apache HTTP service.
Execute:
curl -I http://localhost
This sends an HTTP HEAD request to the local web server.
An example of a successful HTTP response is:
HTTP/1.1 200 OK
Server: Apache/2.4.x (Ubuntu)
Content-Type: text/html
The exact response code depends on the website's configuration. For example, a redirect or authentication response can still show that Apache is accepting connections.
If the service is active but HTTP requests fail, inspect its listener configuration and logs.
Step 16: Confirm that the service remains running.
Execute:
sleep 5
systemctl is-active apache2
Expected:
active
This additional check helps detect a service that starts briefly and then fails.
You can also inspect recent logs:
sudo journalctl -u apache2 -n 20 --no-pager
Confirm that no further startup or runtime failures have occurred.
Step 17: Perform final verification.
Execute:
sudo apache2ctl configtest
systemctl is-active apache2
sudo systemctl status apache2 --no-pager
curl -I http://localhost
The final requirements are:
Verification
Expected result
Apache configuration test
Syntax OK
Apache executable permission
Valid executable permissions
systemd service status
active (running)
HTTP connectivity
A valid response from the configured service
Original startup failure
Resolved
Final Solution
The video suggests the failure may be related to execute permission on /usr/sbin/apache2. The following is the concise command sequence for that specific confirmed failure.
1. Connect to the server.
ssh lfcs00101a
2. Check the service failure.
sudo systemctl status apache2
sudo journalctl -u apache2 -n 50 --no-pager
3. Inspect the Apache executable permissions.
ls -l /usr/sbin/apache2
4. Restore executable permissions if they are incorrect.
sudo chmod 755 /usr/sbin/apache2
5. Validate the Apache configuration.
sudo apache2ctl configtest
6. Start the Apache service.
sudo systemctl start apache2
7. Verify the running service.
sudo systemctl status apache2
systemctl is-active apache2
Expected:
active
8. Verify HTTP connectivity.
curl -I http://localhost
Technical Verification and References
The procedures are consistent with official Apache and systemd documentation:
Apache HTTP Server — apachectl and configtest
Apache HTTP Server — Startup and Troubleshooting
Linux systemctl — Managing Service Units
systemd journalctl — Service Log Inspection
Expected result: The cause preventing apache2 from starting is corrected, and the service is successfully started with systemd and remains in the active (running) state.
Video verification finding: The candidate visibly runs sudo chmod +x /usr/sbin/apache2 and then attempts to restart Apache. That is a valid repair if missing executable permission was the actual fault, but the visible commands do not independently prove the diagnosis or final service state. The diagnostic and verification steps above are necessary for a reliable solution.
Context
You are asked to install a GNU software package from source code.
Task
First, configure the software package at ~/bool with all default settings.
The software package has been unpacked and all tools required for a configuration have been pre-installed for your convenience.
Next, build the software package at ~/bool.
All tools and dependent libraries required for compilation have been pre-installed for your convenience.
Finally, install the built software package.
The Answer Is:
See the complete solution in Explanation.
Explanation:
Objective: Configure, compile, and install the GNU software package already extracted into ~/bool, using its default build and installation settings.
The standard GNU build procedure consists of three main commands, executed in this exact order:
/configure
make
sudo make install
The official GNU Autoconf and Automake documentation confirms this sequence for packages using the GNU build system.
Step 1: Connect to the correct Linux server.
The task is associated with host lfcs00102.
From the candidate terminal, execute:
ssh lfcs00102
This establishes an SSH session with the server where the source-code package must be configured, compiled, and installed.
All subsequent commands must be executed on this host.
Step 2: Navigate to the software source directory.
Execute:
cd ~/bool
cd changes the working directory.
~ represents the current user's home directory.
bool is the directory containing the extracted software source code.
Verify the current directory:
pwd
Expected structure:
/home/candidate/bool
The actual home directory depends on the account used on the host.
Step 3: Inspect the extracted source files.
Execute:
ls -la
A GNU Autotools-based source package commonly contains files such as:
configure
Makefile.am
Makefile.in
configure.ac
README
INSTALL
src/
These are examples of commonly encountered files; the actual directory contents may differ.
The critical file for the first stage is:
configure
The task explicitly states that the package has already been unpacked and the required development tools are installed.
Therefore, there is no need to download another source archive, extract additional files, or install development packages.
Step 4: Verify that the configuration script exists.
Execute:
ls -l ./configure
Then check whether it is executable:
test -x ./configure
echo $?
Expected exit code:
0
If the file is readable but lacks execution permission, you can inspect its permissions:
stat -c '%A %a %n' ./configure
Before changing permissions, confirm that the file is the actual generated configuration script.
If necessary, a readable configure shell script can also be executed with:
sh ./configure
However, the normal and preferred invocation for this task is ./configure.
Step 5: Configure the software package using all default settings.
Execute:
/configure
This is the first essential command.
The configure script examines the system and prepares the source tree for compilation.
Typical checks include:
Operating system and processor architecture.
Available C compiler.
Compiler capabilities and flags.
Required libraries and header files.
Build utilities and dependencies.
Installation directory configuration.
Generation of Makefiles.
An illustrative output might include:
checking for gcc... gcc
checking whether the C compiler works... yes
checking for stdio.h... yes
checking for stdlib.h... yes
checking for make... make
configure: creating ./config.status
config.status: creating Makefile
The output will differ according to the source package.
Important: The task requires all default settings. Therefore, do not specify configuration arguments such as:
/configure --prefix=/opt/bool
or:
/configure --disable-shared
unless explicitly requested.
Using plain ./configure ensures that the package's own default configuration options are selected.
GNU Autoconf documents that the default installation prefix is commonly /usr/local, although packages can choose another default.
Step 6: Verify that configuration completed successfully.
Immediately after ./configure finishes, execute:
echo $?
Expected:
0
Exit status 0 indicates that the configuration script completed successfully.
Next, verify the generated Makefile:
ls -l Makefile
You can also check for the configuration status file:
ls -l config.status
For a standard Autoconf package, these files indicate that configuration generated the instructions required for compilation.
If configuration reports a missing dependency or another error, investigate that specific error before proceeding to the build stage.
Do not assume that configuration succeeded merely because some files were generated.
Step 7: Inspect the generated Makefile.
Execute:
ls -lh Makefile
The Makefile contains the instructions that GNU Make uses to build and install the software.
You can inspect the default installation prefix:
grep -E '^prefix[[:space:]]*=' Makefile
A typical result is:
prefix = /usr/local
This means that the package is configured to install files under /usr/local, unless it defines different destinations.
Common GNU installation directories include:
Directory
Typical purpose
/usr/local/bin
User executables
/usr/local/sbin
Administration executables
/usr/local/lib
Program libraries
/usr/local/include
Header files
/usr/local/share
Architecture-independent data
Do not modify the installation prefix because the task requires the default settings.
Step 8: Build the software package.
Execute the second essential command:
make
This instructs GNU Make to build the software using the generated Makefile.
During compilation, Make may perform operations such as:
Reading the Makefile.
Identifying source files and dependencies.
Invoking the compiler.
Compiling source files into object files.
Linking object files with required libraries.
Producing executable programs or library files.
For a package written in C, an illustrative compilation sequence may look like:
gcc -DHAVE_CONFIG_H -I. -c main.c -o main.o
gcc -DHAVE_CONFIG_H -I. -c util.c -o util.o
gcc -o program main.o util.o
These commands are examples. The actual compilation operations depend on the package.
GNU Make normally builds the default target when invoked without arguments. For standard GNU packages, this is equivalent to the all target.
Step 9: Understand why make should normally run without sudo.
The recommended command is:
make
Not:
sudo make
Building as the normal user is preferable because it avoids creating root-owned intermediate files inside the source directory.
Administrative privileges are generally necessary only when installing files into protected system directories.
Since the task states that all build dependencies are already installed, the compilation should not require additional package installation.
Step 10: Verify that compilation completed successfully.
Immediately after make finishes, execute:
echo $?
Expected output:
0
This confirms that the Make process returned a successful exit status.
If compilation fails, the terminal normally reports an error, such as:
make: *** [Makefile:150: all] Error 2
Such output indicates a failed build.
Investigate the preceding compiler or linker error before continuing.
Do not attempt to install a package that has not built successfully.
Step 11: Confirm the build target is up to date.
You can run:
make
again after a successful build.
If no source files have changed, Make may display:
make: Nothing to be done for 'all'.
Alternatively, it may run a small number of checks or other build commands.
This is expected behavior: Make determines which targets need rebuilding based on its rules and dependencies.
A second build is optional and does not replace checking the first command's exit status.
Step 12: Run the package tests if supported.
Many GNU software packages provide an optional test target:
make check
This runs tests defined by the package's build system.
The official GNU Automake documentation defines make check as the conventional test-suite target.
However, the task does not explicitly require running tests.
Therefore, this step is optional. Use it only if the package provides the target and running the tests is appropriate.
If tests are run, verify their outcome:
echo $?
Expected successful status:
0
Do not confuse make check with make install. Tests validate a build but do not necessarily install it.
Step 13: Install the compiled software package.
After a successful build, execute:
sudo make install
This is the third essential command.
sudo provides administrative privileges.
make executes the build system's specified target.
install invokes the Makefile's installation rules.
The command installs the compiled software into its configured destinations.
Depending on the package, installation may include:
Copying executable binaries.
Installing shared or static libraries.
Installing header files.
Installing documentation and manual pages.
Installing additional package data.
The installation location follows the settings selected during ./configure.
GNU Automake confirms that make install copies the required built files into their installation directories.
Step 14: Do not change the installation destination.
The task specifically requests the default configuration.
Therefore, avoid commands such as:
sudo make install prefix=/opt/custom
Also avoid reconfiguring the package using:
/configure --prefix=/opt/custom
These would change the normal installation destinations.
The appropriate installation command remains:
sudo make install
Step 15: Verify that installation completed successfully.
Immediately after sudo make install finishes, execute:
echo $?
Expected:
0
A zero exit code indicates that the installation target completed successfully.
If installation fails with a permissions error, verify whether administrative privileges were applied correctly and inspect the affected directory.
If a build or dependency error occurs during installation, resolve that error before treating the task as complete.
Step 16: Verify the installation destination.
Inspect the installation prefix recorded in the Makefile:
grep -E '^prefix[[:space:]]*=' Makefile
If the prefix is /usr/local, the installed files will typically be placed in appropriate directories beneath that prefix.
You can inspect standard executable locations:
ls -lt /usr/local/bin/
And, where appropriate:
ls -lt /usr/local/lib/
These commands can help identify newly installed files, but they are not conclusive on their own because other software may already exist in those directories.
For more precise verification, inspect the package's Makefile installation rules or any installation manifest it produces.
Step 17: Verify the installed executable if applicable.
If the package installs an executable, first determine its actual command name from the package's documentation or installation output.
Then execute:
command -v ACTUAL_EXECUTABLE_NAME
For example, if a package installs an executable called example-program:
command -v example-program
You can then check its version if that option is supported:
example-program --version
These commands are illustrative. The directory name bool does not prove that the installed executable is also named bool.
Do not invent an executable name when validating the installation.
Step 18: Run installation checks if the package supports them.
Some GNU packages provide the following target:
make installcheck
This runs checks against installed software rather than files within the build tree.
GNU Automake documents installcheck as an optional target for validating installed programs and libraries.
It is not mandatory for this question.
The task requires configuration, compilation and installation. A successful sudo make install operation satisfies the installation stage.
Step 19: Understand why the three commands must be executed in order.
Order
Command
Purpose
1
/configure
Detects the build environment and prepares Makefiles using default settings
2
make
Compiles and links the source code
3
sudo make install
Installs the built software into the configured system directories
Each stage depends on the preceding stage.
Running make before a successful configuration might fail because the necessary Makefile has not been generated.
Running make install without a successful build may also fail or cause the installation target to attempt compilation. That does not replace the explicitly required build step.
For the LFCS simulation, execute each required stage separately and verify success before continuing.
Step 20: Perform the final verification.
From the source directory:
cd ~/bool
Check the generated Makefile:
test -f Makefile & & echo "Makefile exists"
Check the configuration status file if the package uses Autoconf:
test -f config.status & & echo "Configuration completed"
Confirm the configured prefix:
grep -E '^prefix[[:space:]]*=' Makefile
Check that the build is up to date:
make
Finally, verify the installed files or executable using the actual package name and installation output.
A successful result must satisfy all requirements:
Requirement
Expected result
Correct host
lfcs00102
Source directory
~/bool
Configure with defaults
Successful
Build package
Successful
Install package
Successful
Custom configure options
None
Source extraction
Already completed
Dependency installation
Already completed
Final Solution
The complete essential command sequence is:
Copy commands
# Connect to the designated host
ssh lfcs00102
# Navigate to the extracted source package
cd ~/bool
# Inspect the source files
ls -la
ls -l ./configure
# Step 1: Configure with default settings
/configure
# Step 2: Build the software package
make
# Step 3: Install the built package
sudo make install
To verify the exit status of each stage reliably, use the following alternative, which stops if a required stage fails:
cd ~/bool || exit 1
/configure & &
make & &
sudo make install
This short sequence is appropriate when the provided tools and dependencies are already available, as specified in the task.
Technical Verification and References
The solution has been validated against the official GNU build-system documentation.
GNU Autoconf Manual — Explains the generated configure script and default configuration settings.
GNU Make Manual — Explains compilation using Makefiles and Make targets.
GNU Automake — Standard Targets — Documents make, make check, make install and make installcheck.
Expected result: The GNU software package located at ~/bool is successfully configured using its default settings, compiled using GNU Make, and installed through its Makefile's installation target.
Verification limitation: The prescribed sequence is supported by official GNU documentation. Whether the commands successfully complete on lfcs00102 must be confirmed from their actual terminal output and exit statuses; the supplied recording does not establish an independently tested successful installation.
Task
First, create a user james with the password set to Foundation.
Next, create a group commander with GID 15002 and add user james.
Do not change user james's primary group.
Then, create a group pilot with GID 15001 and edit user james to use pilot as the primary group.
The Answer Is:
See the complete solution in Explanation.
Explanation:
Objective: Create the Linux user james, assign the specified password, create two groups with exact group IDs, and configure the user's primary and supplementary group memberships.
The task requires these operations to be performed in the specified order:
Requirement
Expected configuration
Username
james
Password
Foundation
Supplementary group
commander
Supplementary group GID
15002
Primary group
pilot
Primary group GID
15001
Important: Adding james to commander must not change the user's primary group. Only the final operation changes the primary group to pilot.
Step 1: Connect to the correct Linux server.
The video specifies host lfcs00091.
From the candidate terminal, execute:
ssh lfcs00091
This establishes an SSH connection to the designated Linux server.
All account and group-management operations must be performed on this host.
Step 2: Check whether user james already exists.
Execute:
id james
If the account does not exist, an expected message is:
id: ‘james’: no such user
You can also execute:
getent passwd james
This searches the configured user-account databases.
If the account already exists, inspect it before changing anything. Since the task explicitly requests creating the user, the normal exam starting state should not already contain the account.
Step 3: Create the user james.
Execute:
sudo useradd -m james
sudo runs the command with administrative privileges.
useradd creates a new Linux user account.
-m creates a home directory for the user.
james is the required username.
On a typical Ubuntu system configured for private user groups, the command creates an account with a home directory at:
/home/james
The default primary group is determined by the system's account-creation policy. It is commonly a private group named james.
The official Linux useradd(8) documentation confirms that -m creates a home directory and that default primary-group behavior depends on system configuration.
Linux manual page
Step 4: Verify that the user was created successfully.
Execute:
id james
An illustrative output is:
uid=1001(james) gid=1001(james) groups=1001(james)
The numerical UID and initial GID can differ on the actual system.
Check the account entry:
getent passwd james
Verify the home directory:
ls -ld /home/james
The account should exist before proceeding.
Step 5: Set the user's password to Foundation.
Execute:
sudo passwd james
The system will request a new password.
Enter:
Foundation
When prompted to confirm, enter:
Foundation
The password is case-sensitive.
A successful operation normally displays:
passwd: password updated successfully
The passwd command securely processes the supplied password and updates the account's password authentication information.
The official passwd(1) manual confirms that an administrator can assign a password to another user and that the utility requests the new password interactively.
Linux manual page
Step 6: Verify the user's password status.
Execute:
sudo passwd -S james
The output may resemble:
james P 2026-10-12 0 99999 7 -1
The date and password-aging fields will depend on the system.
The important value is:
P
This indicates that the account has a usable password.
This command does not reveal or independently confirm the plaintext password. To verify the actual credential, authenticate as james using Foundation through an appropriate login method.
Do not attempt to read the plaintext password from /etc/shadow. Linux stores password hashes rather than recoverable plaintext passwords.
Step 7: Check whether the group commander already exists.
Before creating the group, execute:
getent group commander
If the group does not exist, the command normally produces no output.
Also check whether GID 15002 is already allocated:
getent group 15002
If both checks produce no results, the requested group name and ID are available.
Step 8: Create group commander with GID 15002.
Execute:
sudo groupadd -g 15002 commander
groupadd creates a new Linux group.
-g 15002 assigns the exact numerical GID.
commander is the required group name.
The -g option explicitly controls the group's numerical identifier.
The official groupadd(8) documentation confirms that this option creates a group using the specified GID and normally requires it to be unique.
Linux manual page
Step 9: Verify that group commander was created.
Execute:
getent group commander
Expected output, before adding members:
commander:x:15002:
The fields in /etc/group are arranged as:
group_name:password:GID:user_list
Therefore:
commander is the group name.
x indicates the group password field is not stored directly in /etc/group.
15002 is the assigned GID.
The final field lists supplementary group members.
Step 10: Record james's current primary group.
Before adding james to commander, execute:
id -gn james
This displays the user's current primary group name.
To display its numerical GID:
id -g james
On a typical Ubuntu system, the group name may initially be:
james
The purpose of this step is to establish the primary-group value before making any changes to supplementary memberships.
Step 11: Add james to commander as a supplementary group.
Execute:
sudo usermod -aG commander james
This is one of the most important commands in the task.
Option
Purpose
usermod
Modifies an existing user account
-a
Appends to existing supplementary group memberships
-G commander
Specifies the supplementary group
james
Specifies the target user
The combination -aG adds commander to the user's supplementary memberships without changing the primary group.
The official usermod(8) manual confirms this behavior.
Linux manual page
Step 12: Understand why -aG is required.
Compare these commands:
sudo usermod -aG commander james
This is correct because it appends commander to the supplementary groups.
sudo usermod -G commander james
This can replace the user's existing supplementary group list with the specified list, removing memberships that were not included.
sudo usermod -g commander james
This would change the primary group to commander.
The last command is incorrect at this stage because the task explicitly states:
Do not change user james's primary group.
Therefore, use:
sudo usermod -aG commander james
Step 13: Verify supplementary group membership.
Execute:
id james
An illustrative result is:
uid=1001(james) gid=1001(james) groups=1001(james),15002(commander)
This confirms that commander was added as a supplementary group.
Check the group entry:
getent group commander
Expected:
commander:x:15002:james
Step 14: Verify that the primary group has not changed.
Execute:
id -gn james
Compare its output against the primary group recorded in Step 10.
The value must remain unchanged at this stage.
For example, if the original primary group was james, the output should remain:
james
Also check:
id -g james
This should return the original primary GID.
Do not proceed until both conditions are met: james belongs to commander, and the original primary group is unchanged.
Step 15: Check whether the group pilot already exists.
Execute:
getent group pilot
Check whether GID 15001 is available:
getent group 15001
The group name and numerical GID should be available for the requested group creation.
Step 16: Create group pilot with GID 15001.
Execute:
sudo groupadd -g 15001 pilot
groupadd creates a new group.
-g 15001 sets its numerical GID to 15001.
pilot is the requested group name.
The exact GID matters. Do not allow Linux to choose an automatically assigned GID.
Step 17: Verify group pilot.
Execute:
getent group pilot
Expected:
pilot:x:15001:
This verifies the group name and assigned numerical identifier.
At this stage, the group has been created, but the user's primary group has not yet been changed.
Step 18: Set pilot as the primary group for james.
Execute:
sudo usermod -g pilot james
This is the final account-modification command required by the task.
usermod modifies the existing user account.
-g pilot sets the primary login group to pilot.
james identifies the account being modified.
Unlike uppercase -G, which controls supplementary groups, lowercase -g specifies the primary group.
The official usermod(8) documentation distinguishes these options explicitly.
Linux manual page
The new primary group must already exist, which is why pilot was created first.
Step 19: Verify the user's new primary group.
Execute:
id -gn james
Expected output:
pilot
Verify the numerical GID:
id -g james
Expected:
15001
These commands establish that the account's primary group is now pilot.
Step 20: Verify that commander remains a supplementary group.
Execute:
id james
An illustrative final result is:
uid=1001(james) gid=15001(pilot) groups=15001(pilot),15002(commander)
The UID and any additional supplementary groups may differ.
The important conditions are:
Primary GID: 15001, belonging to pilot.
Supplementary membership: commander, GID 15002.
Changing the primary group with usermod -g should not remove the existing supplementary commander membership.
Step 21: Inspect the final account database entry.
Execute:
getent passwd james
An illustrative entry is:
james:x:1001:15001::/home/james:/bin/sh
The fourth field is the primary GID, which must be 15001.
The login shell and other fields may vary according to the system defaults.
Step 22: Verify the group definitions.
Execute:
getent group commander
getent group pilot
Expected group definitions:
commander:x:15002:james
pilot:x:15001:
It is normal for the pilot group entry not to list james explicitly in its final member field. A user's primary group is determined by the GID stored in the user-account record, while /etc/group lists explicit supplementary group membership.
The id james command is the most convenient way to verify both kinds of group membership together.
Linux manual page
Step 23: Verify the password status again.
Execute:
sudo passwd -S james
Confirm that the account still reports a usable password with status P.
The group modifications should not change the password.
Step 24: Perform the final verification.
Execute:
id james
id -gn james
id -g james
id -Gn james
getent group commander
getent group pilot
sudo passwd -S james
The required final configuration is:
Requirement
Expected result
User exists
james
Password configured
Foundation
commander exists
Yes
commander GID
15002
commander membership
Supplementary
pilot exists
Yes
pilot GID
15001
pilot membership
Primary
Other supplementary memberships
Preserved
Final Solution
Execute the following commands in order.
# Connect to the required server
ssh lfcs00091
# Create user james with a home directory
sudo useradd -m james
# Set password interactively to Foundation
sudo passwd james
# Create commander with GID 15002
sudo groupadd -g 15002 commander
# Add james to commander as a supplementary group
sudo usermod -aG commander james
# Verify primary group has not changed
id -gn james
# Create pilot with GID 15001
sudo groupadd -g 15001 pilot
# Change james's primary group to pilot
sudo usermod -g pilot james
# Verify the complete user configuration
id james
id -gn james
id -g james
# Verify the created groups
getent group commander
getent group pilot
# Verify the account has a usable password
sudo passwd -S james
When executing:
sudo passwd james
enter Foundation twice when prompted.
Expected final result:
uid=1001(james) gid=15001(pilot) groups=15001(pilot),15002(commander)
The UID is illustrative. The required group names, GIDs, and memberships must match exactly.
Technical Verification and References
The commands have been checked against the Linux account-management manuals:
Linux useradd(8)
— Creating user accounts.
Linux passwd(1)
— Assigning and checking user passwords.
Linux groupadd(8)
— Creating groups with specified GIDs.
Linux usermod(8)
— Managing primary and supplementary group memberships.
Linux id(1)
— Verifying user and group identities.
Video verification finding: Question 15 is visible at approximately 32:14–32:18 of the recording. Its full task statement and target host lfcs00091 are readable. The candidate moves to the next task without demonstrating these account-management commands, so the solution is independently documentation-verified rather than confirmed through successful execution in the video.
Expected result: User james has password Foundation, belongs to commander (GID 15002) as a supplementary group, and uses pilot (GID 15001) as the primary group.
next now
Worked for 4m 23s
Task
Set the "number of processes" hard limit for the existing user james to 32768 and the soft limit to 16384.
Ensure that changes are made persistently.
The Answer Is:
See the complete solution in Explanation.
Explanation:
Objective: Configure persistent Linux resource limits for the existing user james, ensuring that:
The hard process limit is 32768.
The soft process limit is 16384.
The limits are applied when the user starts a new PAM-managed login session.
The configuration remains available after a system reboot.
The appropriate solution uses Linux-PAM's resource-limit configuration, typically in /etc/security/limits.d/.
The official Linux-PAM documentation specifies the configuration syntax and confirms that nproc is the resource identifier for process limits.
Step 1: Connect to the correct Linux server.
The video specifies host lfcs00089.
From the candidate terminal, execute:
ssh lfcs00089
This establishes an SSH session with the designated server.
All subsequent configuration changes must be performed on this host.
Step 2: Verify that the user james exists.
Execute:
id james
This displays the user's UID, primary group and supplementary group memberships.
Example output:
uid=1001(james) gid=1001(james) groups=1001(james)
The numeric identifiers may differ on the actual server.
You can also check the account database:
getent passwd james
The task specifies an existing user, so there is no need to create a new account or modify the user's password.
Step 3: Understand soft and hard process limits.
Linux implements process-related resource restrictions using RLIMIT_NPROC.
Limit
Required value
Purpose
Soft
16384
Default process/thread creation limit enforced for the user's processes
Hard
32768
Maximum value to which an unprivileged user may raise the soft limit
The hard limit must be at least as large as the soft limit. Here:
\[ 16384 \leq 32768 \]
Therefore, the requested configuration is valid.
On Linux, RLIMIT_NPROC actually accounts for processes and threads associated with the real user ID, subject to kernel privilege exceptions. It is not a separate allowance for every running application.
Step 4: Inspect any existing persistent limits.
Before changing the system, execute:
sudo cat /etc/security/limits.conf
Then list any existing supplemental configuration files:
sudo ls -la /etc/security/limits.d/
Search specifically for process-limit settings:
sudo grep -RnsE \
'^[[:space:]]*([^#[:space:]] +[[:space:]]+)+(soft|hard|-)[[:space:]] +nproc' \
/etc/security/limits.conf /etc/security/limits.d/ 2 > /dev/null
Also check for any existing entries concerning james:
sudo grep -RnsE '^[[:space:]]*james[[:space:]] ' \
/etc/security/limits.conf /etc/security/limits.d/ 2 > /dev/null
These checks help identify existing user-specific limits and avoid contradictory configuration entries.
Step 5: Understand the persistent configuration locations.
The primary resource-limit configuration file is:
/etc/security/limits.conf
Additional administrator-defined limits can be stored under:
/etc/security/limits.d/
Both locations are supported by Linux-PAM.
The configuration format is:
< domain > < type > < item > < value >
For this task:
Field
Required value
Description
Domain
james
Existing username
Type
soft or hard
Which resource limit to configure
Item
nproc
Number of processes/threads
Value
16384 or 32768
Required limit
A dedicated configuration file is preferable because it keeps the account-specific policy separate from the system's general resource-limit settings.
Step 6: Create the persistent configuration file.
Execute:
sudo nano /etc/security/limits.d/90-james-nproc.conf
This opens a new configuration file.
If the file already exists, inspect its contents before modifying it.
Step 7: Add the required soft and hard process limits.
Insert the following two lines:
james soft nproc 16384
james hard nproc 32768
This is the exact configuration required for the task.
Explanation of the first line:
james soft nproc 16384
james selects the target user.
soft specifies the default soft resource limit.
nproc refers to the process/thread limit.
16384 establishes the required soft value.
Explanation of the second line:
james hard nproc 32768
james selects the same user.
hard specifies the hard resource limit.
nproc identifies the resource.
32768 establishes the maximum hard value.
These settings apply specifically to james rather than all users.
The Linux-PAM manual explicitly supports user-specific soft and hard nproc entries.
Step 8: Save the configuration.
If using Nano:
Press Ctrl + O to save.
Press Enter to confirm the filename.
Press Ctrl + X to exit.
If using Vim:
Press Esc.
Type :wq.
Press Enter.
The file should be located at:
/etc/security/limits.d/90-james-nproc.conf
Step 9: Verify the saved configuration.
Execute:
sudo cat /etc/security/limits.d/90-james-nproc.conf
Expected output:
james soft nproc 16384
james hard nproc 32768
Check the file permissions:
ls -l /etc/security/limits.d/90-james-nproc.conf
A typical configuration file has permissions of 644 and is owned by root.
If the file permissions are incorrect, restore appropriate permissions:
sudo chmod 644 /etc/security/limits.d/90-james-nproc.conf
The file should be readable by the PAM module when login sessions are established.
Step 10: Verify that PAM applies resource limits.
The settings are interpreted by the PAM module:
pam_limits.so
Check whether the module is configured:
sudo grep -Rns 'pam_limits.so' /etc/pam.d/
A relevant configuration entry resembles:
session required pam_limits.so
session identifies the PAM session-management phase.
required means the module must succeed for the relevant PAM operation to succeed.
pam_limits.so applies the configured resource limits when the session is established.
The official Linux-PAM documentation confirms that this module applies resource limits to user sessions.
On Ubuntu, inspect the PAM configuration used by the relevant login method, including sshd, login, su, and any referenced common-session files.
Do not blindly add duplicate pam_limits.so entries. If the module is absent from the actual login path, configure it appropriately before testing.
Step 11: Understand when the changes take effect.
The limits defined in /etc/security/limits.d/90-james-nproc.conf are persistent settings, but they are not automatically applied to every currently running process.
Linux-PAM applies these limits when an applicable new login session begins.
Therefore:
Existing sessions may retain their previous limits.
New PAM-managed sessions can receive the new values.
Changes survive reboot because the configuration is stored on disk.
There is no need to restart the entire operating system simply to load the configuration.
The Linux-PAM manual specifically explains that configured resource limits are applied per login session.
Step 12: Start a fresh session as james.
If you have administrative access, you can attempt to create a new login session with:
sudo su - james
This starts a login-style shell using the su PAM service, provided that service is configured to apply PAM resource limits.
Alternatively, open a new SSH login as james, using the account's existing credentials if permitted:
ssh james@localhost
A fresh SSH login is particularly useful if the actual login service is the intended target of the configuration.
Check the active user:
whoami
Expected:
james
Do not assume that simply running sudo -u james ulimit ... is a valid test. ulimit is a shell builtin, and changing the execution user does not necessarily create a PAM session or apply its resource-limit policy.
Step 13: Verify the soft process limit.
Inside the new login session belonging to james, execute:
ulimit -Su
ulimit displays or controls process resource limits.
-S selects the soft limit.
-u selects the maximum process/thread resource limit.
Expected output:
16384
This confirms that the session received the required soft limit.
Step 14: Verify the hard process limit.
In the same session, execute:
ulimit -Hu
-H selects the hard limit.
-u selects the process/thread resource limit.
Expected output:
32768
The GNU Bash manual confirms that -S and -H distinguish soft and hard limits, and that -u refers to the maximum number of processes available to a user.
Step 15: Verify both limits together.
Execute:
printf 'Soft limit: '
ulimit -Su
printf 'Hard limit: '
ulimit -Hu
Expected output:
Soft limit: 16384
Hard limit: 32768
This is the most direct practical verification of the two requested values.
Step 16: Verify the kernel's process-limit information.
Linux also exposes resource limits through the /proc filesystem.
Inside the new james session, execute:
cat /proc/self/limits
Find the line:
Max processes
The relevant values should be:
Limit Soft Limit Hard Limit
Max processes 16384 32768
The displayed output contains additional columns and other resource limits, but the Max processes entry is the one relevant to this task.
For a more concise check, execute:
grep 'Max processes' /proc/self/limits
Expected values:
Max processes 16384 32768
You can also use:
prlimit --pid $$
This displays resource limits for the current shell process.
Step 17: Check for conflicting limits if the values are incorrect.
If the new session does not show the required values, investigate rather than repeatedly adding duplicate configuration entries.
First, inspect user-specific rules:
sudo grep -Rns 'james' \
/etc/security/limits.conf /etc/security/limits.d/
Next, inspect all process-limit rules:
sudo grep -Rns 'nproc' \
/etc/security/limits.conf /etc/security/limits.d/
Then check whether pam_limits.so is active in the login method used for testing.
Potential reasons for an unexpected value include an overriding limits configuration, a session started without PAM resource-limit processing, or resource limits imposed by a systemd-managed service.
If the user runs an application under a systemd service, systemd's LimitNPROC= setting may also be relevant. However, configuring a systemd service is not required by the task.
Step 18: Verify persistence.
The persistent configuration resides at:
/etc/security/limits.d/90-james-nproc.conf
Execute:
sudo cat /etc/security/limits.d/90-james-nproc.conf
Expected:
james soft nproc 16384
james hard nproc 32768
Because this configuration is stored under /etc, it remains present after the system reboots unless it is changed or removed.
For end-to-end verification, start a fresh login session after reboot and repeat:
ulimit -Su
ulimit -Hu
Expected:
16384
32768
A reboot is not necessary for normal verification, and should not be performed unnecessarily during the LFCS exam.
Step 19: Confirm that unrelated users remain unchanged.
The file contains rules for:
james
It does not use the wildcard:
*
Therefore, this particular configuration does not apply indiscriminately to all users.
Avoid adding entries such as:
* soft nproc 16384
* hard nproc 32768
Those would impose the specified limits more broadly, instead of targeting the user named in the task.
Step 20: Perform final verification.
The final configuration must satisfy all requirements:
Requirement
Expected result
Existing user
james
Resource type
nproc
Soft limit
16384
Hard limit
32768
Persistent configuration
Present
Fresh login session
Correct limits applied
Other users
No unnecessary changes
Final Solution
The essential commands are:
Copy commands
# Connect to the correct server
ssh lfcs00089
# Verify the user exists
id james
# Create the persistent resource-limit configuration
printf '%s\n' \
'james soft nproc 16384' \
'james hard nproc 32768' | \
sudo tee /etc/security/limits.d/90-james-nproc.conf
# Verify the configuration
sudo cat /etc/security/limits.d/90-james-nproc.conf
# Confirm PAM resource-limit integration
sudo grep -Rns 'pam_limits.so' /etc/pam.d/
# Start a new PAM-managed login session
# (provided the su PAM stack applies pam_limits)
sudo su - james
# Verify the soft limit
ulimit -Su
# Verify the hard limit
ulimit -Hu
# Verify through procfs
grep 'Max processes' /proc/self/limits
The required configuration is:
james soft nproc 16384
james hard nproc 32768
Technical Verification and References
Linux-PAM limits.conf(5) — Confirms the configuration file syntax and nproc resource identifier.
Linux-PAM pam_limits(8) — Explains how limits are applied when PAM sessions are established.
GNU Bash — ulimit — Documents soft and hard resource-limit verification.
Linux getrlimit(2) — Defines the kernel's process-limit behavior.
Video verification finding: At approximately 29:01–29:05, Question 9 appears with host lfcs00089. The recording shows the full task statement but does not demonstrate the required configuration being completed. The solution above is independently validated against Linux-PAM documentation.
Expected result: User james receives a soft process limit of 16384 and a hard process limit of 32768 in applicable new login sessions. The settings are stored persistently and remain configured after reboot.
Task
Schedule a cron job for user james that:
- runs every day at 17:15
- executes the script /home/james/bin/scanfiles.sh
- sends its STDOUT output to /home/james/report.txt
The Answer Is:
See the complete solution in Explanation.
Explanation:
Step 1: Connect to the correct server.
The video specifies that the task must be completed on host lfcs00082.
From the candidate terminal, connect using:
ssh lfcs00082
This establishes an SSH session with the server where the cron job must be configured.
Step 2: Verify that the user james exists.
Execute:
id james
This displays the user's UID, primary GID, and group memberships.
An example of valid output is:
uid=1001(james) gid=1001(james) groups=1001(james)
The exact numerical IDs may differ. The important requirement is that the user james exists.
Step 3: Verify that the script exists.
Execute:
ls -l /home/james/bin/scanfiles.sh
This verifies the script's location, ownership, and permissions.
You can also check whether james has execute permission:
sudo -u james test -x /home/james/bin/scanfiles.sh
echo $?
An exit status of 0 confirms that the user can execute the script. If the check fails, investigate file and directory permissions.
The task does not require creating or modifying the script.
Step 4: Open the crontab for user james.
Execute:
sudo crontab -u james -e
- sudo provides the privileges needed to manage another user's crontab.
- crontab manages scheduled cron jobs.
- -u james selects the crontab belonging to user james.
- -e opens the selected crontab in a text editor.
This is important because the task explicitly requires scheduling the job for james, not for root or the candidate account.
Step 5: Add the cron job.
Insert the following entry into the crontab:
15 17 * * * /home/james/bin/scanfiles.sh > /home/james/report.txt
This is the exact scheduling command required to satisfy the task.
Step 6: Understand the cron expression.
The cron entry contains five scheduling fields followed by the command.
Field Value Description
Minute 15 Execute at minute 15
Hour 17 Execute at 17:00 (5 PM)
Day of month * Every day of the month
Month * Every month
Day of week * Every day of the week
Therefore, the script executes once daily at 17:15 according to the cron daemon's configured timezone.
The command portion is:
/home/james/bin/scanfiles.sh > /home/james/report.txt
It consists of:
- /home/james/bin/scanfiles.sh — the executable script.
- > — the shell's STDOUT redirection operator.
- /home/james/report.txt — the destination file for standard output.
The > operator creates the report file if it does not exist and the user has permission. If it exists, the output is overwritten on each execution.
Do not replace > with > > because > > appends output. Also, do not use 2 > & 1, because the task requests STDOUT only, not STDERR.
Step 7: Save the crontab.
If the crontab opens in Vim:
1. Press i to enter insert mode.
2. Add the cron entry.
3. Press Esc.
4. Type :wq and press Enter.
If it opens in Nano, press Ctrl+O, Enter, then Ctrl+X.
Once saved, the crontab command installs the updated schedule automatically.
Step 8: Verify the installed cron job.
Execute:
sudo crontab -u james -l
The output must include:
15 17 * * * /home/james/bin/scanfiles.sh > /home/james/report.txt
This verifies that the job is installed under the correct user account.
Step 9: Check the cron service.
On the Ubuntu system shown in the recording, execute:
systemctl status cron
The service should report:
Active: active (running)
If it is inactive, start it:
sudo systemctl start cron
To check whether the service is enabled for startup:
systemctl is-enabled cron
If cron is disabled and must remain operational after reboot, enable it:
sudo systemctl enable cron
Step 10: Verify the final configuration.
Run:
sudo crontab -u james -l
sudo -u james test -x /home/james/bin/scanfiles.sh
systemctl is-active cron
These commands verify that:
1. The required cron entry belongs to james.
2. The script is executable by james.
3. The cron service is active.
The report file is not necessarily present immediately after installing the cron entry. It will be created or overwritten when the scheduled job executes successfully.
Final Solution
The essential command is:
sudo crontab -u james -e
Add:
15 17 * * * /home/james/bin/scanfiles.sh > /home/james/report.txt
Then verify:
sudo crontab -u james -l
Technical verification: This solution follows the documented Linux crontab(1) and crontab(5) syntax. A user-specific crontab executes commands under the owner's account and uses five scheduling fields followed by the command.
Linux manual page
+1
Expected result: The script runs every day at 17:15 as james, directing its standard output to /home/james/report.txt. The schedule's configuration is verified; actual runtime success depends on the script, its permissions, and the target system.