Read and Safely Edit /etc/services on Linux
You will finish with a reliable way to look up service names and ports, add one local mapping without damaging the system file, and check what the resolver actually returns. This guide follows the installed Linux man-pages 6.7 documentation and uses the getent command already present on this machine.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about ten minutes. You need a shell and read access to /etc/services. Reading and checking entries is unprivileged. Editing the file requires root, changes name-to-port data for local programs, and should be done during a maintenance window if applications depend on the mapping. An entry in this file does not start a daemon, open a firewall port or prove that anything is listening.
1. Check which file and package you have
The conventional path is /etc/services. The library constant _PATH_SERVICES, declared through <netdb.h>, defines the path used by programs, so do not assume that a hand-made copy elsewhere is being read.
Confirm the local package version and file path with ordinary, read-only commands:
$ dpkg-query -W -f='${Package} ${Version}\n' manpages
manpages 6.7-2
$ ls -l /etc/services
-rw-r--r-- 1 root root ... /etc/services
The permission line can differ in its date and size fields. The useful checks are that the file exists and is normally owned by root. On a non-Debian system, the package query may not exist; that does not change the file format described below.
2. Look up a name before reading the whole file
Use getent services for the system's name-service lookup rather than relying only on a text search. It asks the C library service database for the result that applications are likely to use:
$ getent services ssh
ssh 22/tcp
$ getent services http/tcp
http 80/tcp www
The output has a service name, a decimal port followed by a slash and protocol, and optional aliases. A lookup may return nothing when a name is absent. Query a port as well as a name when diagnosing a configuration:
$ getent services 22/tcp
ssh 22/tcp
Checkpoint: if the name lookup returns an entry, you have proved that the service database can resolve it. You have not proved that a process is listening. Use a separate tool such as ss to investigate listeners, and treat that as a different question.
3. Read the file's line format
Each active line has this shape:
service-name port/protocol alias1 alias2 # optional comment
Spaces or tabs separate the fields. The service name must start in the first column, is case sensitive, and should use conservative characters such as lowercase letters, digits and hyphens. The protocol should match a protocol known to the system, commonly tcp or udp. Blank lines are ignored and a hash character starts a comment that continues to the end of the line.
Many assigned services have separate TCP and UDP entries. Do not merge them just because the port number is the same. These are distinct mappings:
example-dns 5353/tcp
example-dns 5353/udp
Keep one protocol per line. A line that does not match the format may be silently skipped by the lookup routines on this system, but that behaviour is not a safe validation strategy.
4. Make a reversible backup before editing
Editing /etc/services is a privileged operation. Before changing it, preserve the current file and record its metadata. Run the following with sudo only if your account is authorised to administer the machine:
$ sudo cp --preserve=all /etc/services /etc/services.bak
$ sudo ls -l /etc/services /etc/services.bak
This backup is a recovery point, not a permanent archive. Do not overwrite it repeatedly while experimenting. If the edit is wrong, restore it explicitly and then verify the lookup again:
$ sudo cp --preserve=all /etc/services.bak /etc/services
$ getent services example-internal
Restoring the backup discards later edits to this file. Confirm that it is the backup you intend to use before running the command.
5. Add a local mapping with a temporary file
Choose a name that will not be confused with an IANA-assigned service. Use a port and protocol that match the application you are configuring. The example below adds a private TCP mapping on port 18080. It does not bind the port or launch anything.
First inspect the target line without changing the file:
$ grep -nE '^[[:space:]]*example-internal([[:space:]]|$)' /etc/services || true
If no line is printed, create a temporary copy, append the entry, inspect it, then install it with root ownership and mode. The temporary file stays in /tmp until the final command succeeds:
$ tmp_services=$(mktemp)
$ cp --preserve=all /etc/services "$tmp_services"
$ printf '%s\n' 'example-internal 18080/tcp # local application' >> "$tmp_services"
$ tail -n 3 "$tmp_services"
$ sudo install --owner=root --group=root --mode=0644 "$tmp_services" /etc/services
$ rm "$tmp_services"
$ getent services example-internal
example-internal 18080/tcp
Check the output before installing. The temporary file contains a copy of the whole database, so a typo in the appended line is easier to spot there than after a direct edit. The rm removes only the temporary file after installation; it is not the recovery backup.
6. Diagnose a missing or misleading result
If getent services example-internal prints nothing, check the spelling, first-column position and exact protocol. Names are case sensitive. Also inspect the actual file:
$ grep -nF 'example-internal' /etc/services
$ getent services 18080/tcp
If the file contains a line but getent does not return it, investigate the host's name-service configuration and the line's syntax before making another edit. Do not add spaces before the service name, use a comma in place of the slash, or put a comment in the middle of the port and protocol field.
To distinguish this database from a live network service, check listeners separately:
$ ss -ltn '( sport = :18080 )'
State Recv-Q Send-Q Local Address:Port Peer Address:Port
An empty listener result is expected if no program has bound port 18080. The /etc/services entry still lets programs translate the name to that port. Ports below 1024 are normally restricted to root when a process binds them, but adding a text entry does not grant that privilege and does not bypass firewall policy.
Done means
getent services NAMEreturns the expected port and protocol.- The entry uses a first-column name, decimal port, slash, valid protocol and optional aliases or comment.
- TCP and UDP mappings are separate when both are required.
- The file was backed up before the privileged edit, and the backup can restore the previous state.
- You checked the lookup separately from whether a process is listening or a firewall permits traffic.