Skip to content

What is $PATH?

The $PATH environment variable is a critical component in Unix-like operating systems, including Linux and macOS. It helps the system determine where to look for the executable files for commands and programs.

And you can type:

$ echo $PATH
To see the current $PATH values


How to modify $PATH?

You can modify $PATH to include additional directories where custom scripts or software are stored. This is done using the export command in the shell. For example, to add /usr/local/my_program/bin to $PATH, you can use:

export PATH=/usr/local/my_program/bin:$PATH


What does >> means in shell commands?

The >> operator in shell commands is used for appending output to the end of a file. It's often used in conjunction with commands like echo to redirect the output from the command line to a file, without overwriting the existing contents of the file.


Difference Between > and >>

  • > is used for redirection and it overwrites the file with the new content.
  • >> is also used for redirection but it appends the new content to the existing content of the file, preserving the original contents.

What are the shell exit code?

In Unix-like operating systems, shell scripts and commands return an exit status (also known as an exit code or return status) upon completion. This exit code is an integer value from 0 to 255, which is returned to the parent process. These codes are important for scripting and automation, as they can indicate success or various types of errors or statuses. Here are some of the common exit codes:

Common Exit Codes

  • 0: Success. This code indicates that the command or script executed successfully without any errors.
  • 1: General error. This is a catch-all for general errors. It is often used as the default exit code when the script fails for an unspecified reason.
  • 2: Misuse of shell builtins. According to the Bash documentation, this exit status indicates misuse of shell builtins, although in practice, it can be used by a program to indicate different types of errors.
  • 126: Command invoked cannot execute. This return code indicates that the command cannot execute, possibly due to permissions issues or because it is not an executable.
  • 127: Command not found. This exit code means that the command could not be found, which often occurs when the command is typed incorrectly or the command's binary is not in the PATH.
  • 128: Invalid argument to exit. This is returned if exit is called with a status outside the range of 0 to 255, typically caused by an incorrect script programming.
  • 128+n: Fatal error signal "n". This status code is used by the shell to indicate that the process was terminated by signal "n". For example, 128 + 9 (SIGKILL) returns 137.
  • 130: Script terminated by Control-C. This is returned when a script is terminated by Control-C, which sends the SIGINT signal (interrupt signal).
  • 255*: Exit status out of range. This is returned if the exit status is outside the valid range 0 to 255.

What does $? means in shell

In shell scripting, $? is a special variable that represents the exit status of the last command or script executed in the foreground. It captures the output of the exit status of a command, which is an integer value indicating whether the command succeeded or failed, and if it failed, how it failed.

Meaning of $?

  • 0: The command was successful without any errors.
  • Non-zero value: The command failed. The specific non-zero value can provide information about what type of error occurred, according to the conventions of the specific command.

Usage of $?

The $? variable is often used in shell scripts and command lines to check the success or failure of commands and to make decisions based on those outcomes. Here is an example of how $? might be used in a script:

#!/bin/bash

# Attempt to copy a file
cp myfile.txt /destination/directory/
# Check if the copy command was successful
if [ $? -eq 0 ]; then
    echo "File copied successfully."
else
    echo "Failed to copy file."
fi

In this script, cp myfile.txt /destination/directory/ attempts to copy a file. Immediately after this command, [ $? -eq 0 ] checks the exit status. If the status is 0, the script prints that the file was copied successfully. If not, it prints a failure message.

This approach is very common in shell scripting for error handling and conditional execution based on the success of commands.


How to read systemctl is-active psacct > /dev/null 2>&1

It is used to check the activity status of the psacct service on systems that use systemd for service management. 1. systemctl is-active psacct: - systemctl is the command-line interface for interacting with the systemd system and service manager. - is-active is a subcommand used to check if a specified systemd service is currently active (i.e., running). - psacct is the name of the service being checked. The psacct service is used for monitoring process activities, which logs information about system usage and can be used for generating reports about user consumption. 2. > /dev/null: - This part of the command redirects the standard output (stdout) to /dev/null. The device /dev/null is a special file that discards all data written to it, essentially acting as a black hole for data. - This redirection is used here to hide the output of the systemctl is-active psacct command. Normally, this command prints "active" or "inactive" to stdout based on the service's status. 3. 2>&1: - This syntax is for redirecting standard error (stderr) to the same destination as standard output (stdout), which has already been redirected to /dev/null. - 2 represents stderr, and 1 represents stdout. So 2>&1 means "redirect stderr to wherever stdout is currently going." - This is used to ensure that both the standard output and any error messages are ignored and not displayed on the console.


Regular Expression aka Regex

Basic Regular Expressions (BRE)

  • . Matches any single character except newline.
  • ^ Matches the beginning of the line.
  • $ Matches the end of the line.
  • [...] Matches any one of the characters enclosed.
  • [^...] Matches any one character not enclosed.
  • * Matches zero or more occurrences of the preceding element.
  • \{n\} Matches exactly n occurrences of the preceding element.
  • \{n,\} Matches n or more occurrences of the preceding element.
  • \{n,m\} Matches between n and m occurrences of the preceding element.

Special Characters: - \ Escapes a special character. - The metacharacters ?, +, (, ), and | lose their special meaning within BRE; instead backslashes are used.

Note: Backslashes \ are used to escape special characters in BRE.

Extended Regular Expressions (ERE)

  • . Matches any single character except newline.
  • ^ Matches the beginning of the line.
  • $ Matches the end of the line.
  • [...] Matches any one of the characters enclosed.
  • [^...] Matches any one character not enclosed.
  • * Matches zero or more occurrences of the preceding element.
  • + Matches one or more of the preceding element.
  • ? Matches zero or one of the preceding element.
  • {n} Matches exactly n occurrences of the preceding element.
  • {n,} Matches n or more occurrences of the preceding element.
  • {n,m} Matches between n and m occurrences of the preceding element.
  • | Alternation, matches any one of the expressions separated by |.
  • () Grouping expressions to be treated as a single unit.

Special Characters: - \ Escapes a special character. - Parentheses (), curly braces {}, the plus sign +, the question mark ?, and the vertical bar | all have special meanings in ERE.

Note: ERE does not require backslashes for the above special characters, unlike BRE.

Regular Expression Examples

Go regex101.com to test your regex 1. Matching a Specific Word

**BRE:** `\<word\>`
**ERE:** `\bword\b`
**Description:** Matches the word 'word' as a whole word.

- **BRE Explanation:** The `\<` and `\>` are word boundary markers in BRE.
- **ERE Explanation:** The `\b` is a word boundary marker in ERE.

  1. Matching a Number
    BRE: `[0-9]\+`
    ERE: `[0-9]+`
    Description: Matches one or more digits.
    
    - BRE Explanation: The `\+` means one or more of the preceding element (digits here).
    - ERE Explanation: The `+` directly indicates one or more of the preceding element without needing a backslash.
    
  2. Matching an Email Address
    BRE: `[[:alnum:]_.]+@[[:alnum:]_.]+\.[[:alpha:]]\{2,4\}`
    ERE: `[[:alnum:]_.]+@[[:alnum:]_.]+\.[[:alpha:]]{2,4}`
    Description: Matches a basic email address format.
    
    - BRE Explanation: Uses `\{n,m\}` to specify the length of the top-level domain.
    - ERE Explanation: Uses `{n,m}` without backslashes to specify the length.
    
  3. Matching IPv4 Addresses
    BRE: `\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}`
    ERE: `([0-9]{1,3}\.){3}[0-9]{1,3}`
    Description: Matches a simple IPv4 address.
    
    - BRE Explanation: Uses escaped parentheses for grouping and `\{n,m\}` for repetition.
    - ERE Explanation: Parentheses and curly braces are used directly without escapes.
    
  4. Capturing Groups and Alternation
    BRE: `\(foo\|bar\)\+`
    ERE: `(foo|bar)+`
    Description: Matches one or more occurrences of 'foo' or 'bar'.
    
    - BRE Explanation: The `\(` and `\)` denote capturing groups, and `\|` is used for alternation.
    - ERE Explanation: Direct use of `(`, `)`, and `|` for capturing groups and alternation.
    

GUI for crontab Schedule Expressions

https://crontab.guru/

What is Systemd Timer?

Systemd timer units are a feature of the systemd init system in Unix-like operating systems. They allow users to schedule tasks or services to run at specific times or intervals. Essentially, systemd timers are systemd units that control the execution of other units (such as services) based on defined time conditions.

Key Points:

  1. Automation: Systemd timers enable automation of recurring tasks, similar to cron jobs, but they offer more flexibility and integration with other systemd features.

  2. Accuracy: Timers can be more accurate than traditional cron jobs because they are aware of system events such as system sleep or shutdown and can compensate accordingly.

  3. Integration: Timers are integrated with other systemd components, such as service units, making it easier to manage dependencies and control the execution of tasks.

  4. Persistent and Monotonic Time: Timers use monotonic time, which is not affected by changes in the system's real-time clock. This ensures more accurate timing, especially on systems with irregular clock adjustments.

  5. Unit File Format: Timer units have a similar unit file format to service units, with sections such as [Unit], [Timer], and [Install]. The [Timer] section defines when and how often the timer should trigger.

  6. Activation Types: Timers can be configured to activate services in various ways:

  7. OnCalendar: Specifies a calendar-based schedule (e.g., daily, weekly, or specific dates).
  8. OnActiveSec: Specifies a relative time to trigger after the timer is activated.
  9. OnBootSec: Specifies a relative time to trigger after booting the system.
  10. OnStartupSec: Similar to OnBootSec, but triggered only once after the system boots.
  11. OnUnitActiveSec: Specifies a relative time to trigger after a specified unit becomes active.
  12. OnUnitInactiveSec: Specifies a relative time to trigger after a specified unit becomes inactive.

Overall, systemd timers provide a robust and flexible mechanism for scheduling tasks and services on Linux systems, offering advantages in accuracy, integration, and management over traditional cron jobs.

Comparison: Systemd Timer vs crontab vs anacron vs anacrontab

  1. Systemd Timers:
  2. Automation: Schedule tasks or services to run at specific times or intervals, offering flexibility and integration with other systemd units.
  3. Accuracy: More accurate than traditional cron jobs as they are aware of system events like sleep or shutdown.
  4. Unit File Format: Similar to service units, providing consistency and ease of management.
  5. Activation Types: Various activation types such as OnCalendar, OnActiveSec, and OnBootSec.
  6. Integration: Integrated with other systemd components, simplifying management and dependencies.

  7. crontab:

  8. Widely Used: Traditional Unix tool for scheduling periodic tasks like backups and maintenance.
  9. Text-Based Configuration: Jobs are defined in a text file called the crontab file, which can be edited using the crontab command.
  10. Limited Flexibility: Basic scheduling capabilities, may lack advanced features and integrations of systemd timers.

  11. anacron:

  12. Handling Missed Jobs: Executes periodic tasks on systems that may not be continuously running, compensating for missed runs.
  13. Scheduling: Typically used for tasks that need to run daily, weekly, or monthly.
  14. Separate Configuration: Uses anacrontab for defining jobs and schedules.

  15. anacrontab:

  16. Configuration File: Defines jobs and their schedules for anacron to execute.
  17. Similar to crontab: Serves a similar purpose to crontab in terms of defining periodic tasks.
  18. More Flexible Scheduling: Provides more flexibility in scheduling compared to crontab, especially for systems with irregular availability.

In summary, while all these tools serve the purpose of scheduling tasks on Unix-like systems, they have different features and use cases. Systemd timers offer integration and precise scheduling, crontab is widely used and simple to configure, anacron compensates for missed runs on intermittently available systems, and anacrontab provides more flexible scheduling for anacron jobs. The choice depends on the specific requirements and preferences of the user and system environment.


PID (Process ID)

Overview

  • Definition: PID stands for Process ID.
  • Purpose: It uniquely identifies a running process in the system.
  • Uniqueness: Each process has a unique PID at any given time. PIDs are generally reused after a process terminates.

Characteristics

  • Assignment: Assigned by the operating system when a process is created.
  • Scope: Specific to the system's running instance; the same PID can be reused after the process ends.
  • Lifetime: A PID is valid only as long as the process it identifies is running.

Usage

  • Process Management: Used in various commands for process management.
  • ps: Lists currently running processes along with their PIDs.
  • kill <PID>: Terminates a process identified by the specified PID.
  • top: Displays system tasks and their PIDs.
  • Example:
  • ps -e: Displays all running processes with their PIDs.

Example

  • Running ps -e might output:
    PID TTY          TIME CMD
      1 ?        00:00:02 systemd
    630 ?        00:00:00 sshd
    711 ?        00:00:00 bash
    730 ?        00:00:00 ps
    

UID (User ID)

Overview

  • Definition: UID stands for User ID.
  • Purpose: It uniquely identifies a user account in the system.
  • Uniqueness: Each user, including system and service accounts, has a unique UID.

Characteristics

  • Assignment: Assigned when a user account is created.
  • Scope: Persistent across reboots and used for file ownership and permissions.
  • Types:
  • Root User: Typically has UID 0.
  • System Users: Generally have UIDs ranging from 1 to specific system-defined limits.
  • Regular Users: Start with a UID above the system-defined limit (often starting at 1000 or 500).

Usage

  • File Ownership and Permissions: Used to determine the ownership and permissions of files and directories.
  • ls -l: Displays file ownership by UID (converted to username) and GID.
  • chown <UID>:<GID> <file>: Change the file ownership.
  • /etc/passwd: Contains mappings of UID to usernames.
  • Authentication and Authorization: Used in authentication processes to grant or deny access to system resources.
  • Example:
  • The line in /etc/passwd:
    johndoe:x:1001:1001:John Doe:/home/johndoe:/bin/bash
    
    Indicates that the user johndoe has UID 1001.

Example

  • Checking a user's UID:
  • id -u johndoe: Outputs 1001 if the user johndoe has UID 1001.
  • Listing files with ownership:
  • Running ls -l might output:
    -rw-r--r--  1 johndoe johndoe  2048 Mar 12 14:23 file.txt
    

Summary PID vs UID

In Linux, PID and UID are both identifiers used by the system, but they serve different purposes and are associated with different entities.

  • PID (Process ID):
  • Purpose: Uniquely identifies a running process.
  • Scope: Valid only while the process is running.
  • Example Usage: Managing processes, e.g., kill <PID> to terminate a process.
  • Assigned By: Operating system at process creation.

  • UID (User ID):

  • Purpose: Uniquely identifies a user account.
  • Scope: Persistent across system reboots, used for file ownership and permissions.
  • Example Usage: Setting file permissions, authenticating users.
  • Assigned By: System administrator or automated during user account creation.

Understanding the difference between PID and UID is essential for effective system administration and user management in Linux.


Network Time Protocol (NTP)

Overview

Network Time Protocol (NTP) is a networking protocol designed to synchronize the clocks of computers over a network. It ensures that the systems' times are accurate and consistent with a reference time source, typically Coordinated Universal Time (UTC).

Key Concepts

Purpose

  • Time Synchronization: NTP's primary purpose is to synchronize the clocks of devices on a network to within a few milliseconds of UTC.
  • Accuracy and Precision: Provides high accuracy and precision by using a hierarchical system of time sources.

How It Works

  • Stratum Levels: NTP uses a layered hierarchy of time sources called strata.
  • Stratum 0: High-precision timekeeping devices like atomic clocks and GPS clocks.
  • Stratum 1: Servers directly connected to Stratum 0 devices.
  • Stratum 2: Devices that synchronize with Stratum 1 servers, and so on.
  • Client-Server Model: Devices on the network (clients) synchronize their clocks by communicating with NTP servers.
  • Timestamps: NTP operates by exchanging timestamps between clients and servers to calculate the correct time.

Components

  • NTP Server: Provides accurate time to clients. Obtains time from a Stratum 0 device or another NTP server.
  • NTP Client: Requests time from an NTP server and adjusts its local clock.
  • NTP Daemon: (e.g., ntpd on Unix-like systems) Runs continuously to maintain accurate time.

Comparison Between rsync and sftp

Both rsync and sftp are tools used for transferring files between systems in Unix-like operating systems. However, they have different purposes, capabilities, and use cases. Here’s a detailed comparison:

Overview

rsync

rsync is a powerful tool for copying and synchronizing files and directories between different locations. It uses a delta-transfer algorithm to transfer only the changed parts of files, making it efficient for synchronization tasks.

sftp

sftp (SSH File Transfer Protocol) is a secure file transfer protocol that operates over the SSH protocol. It provides secure file access, transfer, and management capabilities.

Key Features

rsync

  • Efficient Transfers: Uses delta encoding to transfer only changed parts of files.
  • Checksum Verification: Ensures data integrity by using checksums.
  • Compression: Supports on-the-fly data compression to reduce transfer size.
  • SSH Support: Can use SSH for secure transfers.
  • Backup Capability: Can be used for incremental backups with hard links.

sftp

  • Security: All data is encrypted during transfer using SSH.
  • Interactive Mode: Allows interactive file management similar to FTP.
  • Standard Protocol: Complies with SSH-2 protocol standards.
  • File Management: Supports a variety of file operations (e.g., chmod, ls, cd).

Commands and Usage

rsync Commands and Usage

  • Basic Syntax: rsync [options] source destination
  • Example: Synchronizing a local directory to a remote server:
    rsync -avz /local/dir user@remote:/remote/dir
    
    -a: Archive mode (preserves permissions, timestamps, etc.)

-v: Verbose output

-z: Compress file data during transfer

Example: Synchronizing a remote directory to a local directory:

rsync -avz user@remote:/remote/dir /local/dir

sftp Commands and Usage

  • Basic Syntax: sftp [options] [user@]host
  • Example: Starting an interactive SFTP session:
sftp user@remote
  • Interactive Mode Commands:
    • ls: List files in the current directory on the remote server.
    • cd : Change directory on the remote server.
    • get : Download a file from the remote server to the local machine.
    • put : Upload a file from the local machine to the remote server.
    • chmod : Change file permissions on the remote server.
    • exit: Exit the SFTP session.

Use Cases

rsync Use Cases

  • Data Synchronization: Efficiently synchronize files and directories between two locations.
  • Incremental Backups: Perform incremental backups to local or remote storage.
  • Mirroring: Maintain a mirror copy of directories for replication and redundancy.

sftp Use Cases

  • Secure File Transfer: Transfer files securely between a local and a remote system.
  • Remote File Management: Manage files on a remote server in an interactive SSH session.
  • Batch Transfers: Use non-interactive mode for scripted file transfers.

Advantages

rsync Advantages

  • Efficiency: Transfers only modified parts of files, reducing bandwidth usage.
  • Versatility: Supports a wide range of options for customization.
  • Backup and Archival: Useful for creating efficient backups and archives.

sftp Advantages

  • Security: Encrypted transfers ensure data privacy and integrity.
  • Simplicity: Easy to use for simple file transfers and remote file management.
  • Compatibility: Works out-of-the-box on any system with SSH. Summary

  • rsync:

    • Strengths: Efficient, versatile, supports incremental backups.
    • Use Cases: Data synchronization, backups, mirroring.
    • Security: Can use SSH for secure transfers.
  • sftp:

    • Strengths: Secure, easy to use, supports interactive and batch modes.
    • Use Cases: Secure file transfers, remote file management.
    • Security: Built-in encryption via SSH.

Depending on your specific needs, both rsync and sftp can be valuable tools for file transfer and synchronization tasks in Unix-like environments.

What is a Daemon?

Overview

A daemon is a background process that runs continuously and performs specific functions or waits to handle specific events. Daemons are common in Unix-like operating systems and are typically started at boot time or when needed, running without direct user interaction.

Key Characteristics

  • Background Process: Runs in the background, often without an associated user interface.
  • Long-Running: Stays active for an extended period, typically from system startup to shutdown.
  • Service Provider: Provides various services such as web hosting, email handling, file serving, and system logging.
  • Automatic Startup: Often configured to start automatically during the system boot process.
  • Ending with 'd': Many daemon names end with the letter d to signify that they are daemons (e.g., httpd for an HTTP server, sshd for an SSH server).

Common Daemons

  • sshd: Provides secure shell access to the system.
  • httpd: Serves web pages for a web server.
  • cron: Executes scheduled tasks.
  • syslogd: Handles logging of system messages.
  • ntpd: Synchronizes the system clock with network time servers.

How Daemons Work

  • Startup: Daemons are typically started by init systems like systemd, Upstart, or the older SysVinit. They can also be started manually via the command line.
  • Parent Process: Daemons often detach from the parent process, becoming child processes of the init system.
  • Process Lifecycle: They are designed to run indefinitely and handle tasks or requests as they come. They can be stopped, started, or restarted as needed using system commands or management tools.
  • Communication: Daemons often communicate with other processes or services using inter-process communication (IPC) mechanisms, such as sockets, pipes, or shared memory.

Advantages of Daemons

  • Automation: Daemons handle tasks automatically without user intervention.
  • Performance: Can run continuously, ensuring services are always available.
  • Security: By running in the background and with limited user interaction, daemons can operate with reduced privileges, enhancing security.

Summary

A daemon is a background process in Unix-like operating systems that provides various services and functionalities without direct user interaction. Daemons are essential for automating and managing system tasks, and they can be controlled using tools provided by the operating system, such as systemd. Examples of daemons include sshd for secure shell access, httpd for web serving, and cron for scheduled tasks.


semanage boolean vs semanage fcontext

Overview

semanage is a command-line tool in SELinux used to manage various aspects of SELinux policy, including Booleans and file contexts. Knowing when to use semanage boolean versus semanage fcontext depends on the specific administrative task you need to accomplish. Both serve distinct purposes in managing SELinux policies.

semanage boolean

Used to enable or disable SELinux Booleans, which are tunable policy elements that modify the behavior of SELinux policies dynamically.

semanage fcontext

Used to manage default file context mappings for files and directories, ensuring the correct SELinux context is applied automatically when files are created or labeled.

Key Differences

semanage boolean

  • Purpose: Toggles specific security features within SELinux policies.
  • Usage: Modify the behavior of SELinux policies dynamically without requiring policy recompilation or relabeling.
  • Persistence: Changes are persistent and survive reboots when the -P flag is used with setsebool.

semanage fcontext

  • Purpose: Defines the default SELinux contexts for files and directories based on path patterns.
  • Usage: Ensures specific files and directories have the correct SELinux context applied, especially important for newly created files.
  • Persistence: Changes are stored and applied during file creation, relabeling, or when restorecon is executed.

Common Use Cases

semanage boolean

Scenario: Enabling Web Server Features

If you need to allow the web server to connect to the network, enabling an SELinux Boolean such as httpd_can_network_connect would be appropriate.

sudo setsebool -P httpd_can_network_connect on
  • Why Use semanage boolean: This is a straightforward way to toggle specific SELinux policy features on or off, tailored to your system’s operational needs. For instance, enabling network access for a web server does not require file relabeling but does require SELinux policies to permit such actions dynamically.

semanage fcontext

Scenario: Configuring File Contexts for a Web Directory

If you set up a new web directory and need it to have the correct SELinux context (httpd_sys_content_t) automatically, you would define the context using semanage fcontext.

sudo semanage fcontext -a -t httpd_sys_content_t "/var/www/html(/.*)?"
sudo restorecon -R /var/www/html
  • Why Use semanage fcontext: This ensures that files and directories within /var/www/html are automatically labeled with the correct context, making it easier to manage file permissions and security automatically. It is essential for maintaining consistent security labeling and ensuring that access controls are correctly enforced.

Example Scenarios

Example 1: Allow Apache to Connect to Databases

Task: You want your Apache web server to connect to a database server over the network.

Solution: Enable the httpd_can_network_connect_db Boolean.

sudo setsebool -P httpd_can_network_connect_db on

Why Use This: Modifying the Boolean dynamically changes the SELinux policy to allow Apache to make network connections to databases, without needing a relabel or specific file context changes.

Example 2: Set Default Context for Custom Application Data

Task: You have a directory /opt/myapp/data for application data that should always have a custom SELinux context myapp_data_t.

Solution: Define the file context with semanage fcontext and apply it.

sudo semanage fcontext -a -t myapp_data_t "/opt/myapp/data(/.*)?"
sudo restorecon -R /opt/myapp/data

Why Use This: Ensures that any files or directories created within /opt/myapp/data will automatically receive the myapp_data_t context, enforcing the correct access controls and reducing manual labeling errors.

Summary

semanage boolean:

  • Purpose: Enable or disable specific SELinux policy features dynamically.
  • Use Cases: Adjusting web server permissions, allowing specific network connections, toggling service-specific permissions.
  • Command Example: sudo setsebool -P httpd_can_network_connect on

semanage fcontext:

  • Purpose: Define and manage default SELinux contexts for file and directory paths.
  • Use Cases: Ensuring correct labeling of web directories, application data directories, custom paths.
  • Command Example:
    sudo semanage fcontext -a -t httpd_sys_content_t "/var/www/html(/.*)?"
    sudo restorecon -R /var/www/html