Network info

getservent#

Read the next entry from the system services database.

getservent walks the /etc/services database one record at a time, yielding the same list of fields as getservbyname and getservbyport but without a lookup key. Each call advances an internal cursor; the cursor is opened on the first call, rewound by setservent, and released by endservent. It mirrors the POSIX getservent(3) C library routine and inherits every portability quirk that implies.

Synopsis#

my ($name, $aliases, $port, $proto) = getservent;
my $name = getservent;        # scalar context

What you get back#

In list context, four fields matching the order documented for every getserv* variant:

  • $name — canonical service name, e.g. "http".

  • $aliases — space-separated string of alternate names, e.g. "www www-http". Not an array; split it yourself if you need one.

  • $port — port number as a native (host-byte-order) integer, e.g. 80.

  • $proto — transport protocol, typically "tcp" or "udp".

In scalar context, just $name. When the cursor reaches end of file, getservent returns the empty list in list context and undef in scalar context — the idiomatic while (my @e = getservent) loop relies on this.

To convert the aliases into a list:

my @alt = split / /, $aliases;

Global state it touches#

  • Internal database cursor for /etc/services — shared with getservbyname, getservbyport, setservent, and endservent. Any by-name or by-port lookup on some platforms rewinds or closes this cursor as a side effect; iterate in a tight loop or wrap the iteration in setservent / endservent to be safe.

  • $! — set when the underlying C call reports an error.

  • Not thread-safe. getservent keeps per-process, not per-thread state; two threads iterating concurrently will interleave records and neither will see the full list.

Examples#

Walk the full services database and print each entry:

while (my ($name, $aliases, $port, $proto) = getservent) {
    print "$name/$proto $port\n";
}
endservent;

Reset the cursor before iterating so earlier calls elsewhere in the program cannot leave it mid-stream:

setservent(0);
while (my @e = getservent) {
    # @e is ($name, $aliases, $port, $proto)
}
endservent;

Collect only TCP services into a hash keyed by port:

my %tcp;
while (my ($name, undef, $port, $proto) = getservent) {
    $tcp{$port} = $name if $proto eq 'tcp';
}
endservent;

Use the object-oriented by-name interface from Net::servent, which overrides the built-in and returns a blessed object with accessor methods:

use Net::servent;
while (my $s = getservent) {
    printf "%-20s %5d/%s\n", $s->name, $s->port, $s->proto;
}

Edge cases#

  • End of file returns empty / undef, not an error. A single-scalar false value in list context (my @e = getservent giving an empty list) is the terminator. Do not check $! to detect end of iteration.

  • Missing /etc/services: on systems without the file, the first call returns the empty list immediately and $! is set. Nothing in the call signals the difference between an empty database and a missing one — inspect $! before assuming the database was simply empty.

  • Cursor sharing with by-name / by-port lookups: calling getservbyname or getservbyport in the middle of a getservent loop may reset the cursor on some platforms. Either finish the walk first or re-open with setservent.

  • $aliases is a string, not a list. split / /, $aliases gives you the array form. Treating $aliases as a list directly silently gives you the length of a one-element list.

  • Threaded programs: iteration is per-process. Coordinate access with a lock, or prefer getservbyname / getservbyport for point queries in threaded code.

  • Scalar context returns only the name. If you need the port, call in list context even when you only care about one field.

Differences from upstream#

Fully compatible with upstream Perl 5.42.

See also#

  • getservbyname — look up a single service by its textual name instead of iterating

  • getservbyport — look up a single service by its numeric port

  • setservent — rewind the shared cursor before iterating so prior calls cannot leave it mid-stream

  • endservent — release the cursor when the walk is done, freeing the underlying file descriptor

  • getprotoent — same iterator pattern for /etc/protocols, typically paired when resolving a (port, proto) tuple

  • Net::servent — object-oriented wrapper whose accessors remove the need to remember field order