An investigation into slow sudo command
In recent days I created a new virtual machine with ubuntu 20.04, but I found the terminal command with sudo
took a long time, almost 3 seconds each time. When I seach sudo command slow
in Google, the first two search results are both from stackflow and suggest adding an entry 127.0.0.1 hostname
to /etc/hosts
file. I checked /etc/hosts
and found the entry 127.0.0.1 hostname
exists (in fact I made a mistake here, which I will describe later). This article describes the investigation into this issue in timeline.
Investigation process
Firstly I use the strace to record system calls information of a sudo
command.
1 | sudo strace -r -T -o sudo_strace.log -e trace=all sudo echo hi |
From the output of strace I find a suspicious point, poll
read from fd=4
costs 2.915s, based on the context of this system call, it is a DNS resolution for hostname ubuntuwork.internal.xxx
. There exist several questions
- Why the DNS resolution for hostname doesn’t use host table directly
- Why there is a DNS resolution for
ubuntuwork.internal.xxx
- Why sudo command has a DNS resolution for hostname
- Is there a DNS cache working
1 | 0.000103 socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 4 <0.000043> |
- For the first question, I re-check the hosts file and hostname, and find the mistake in hostname setting. From hostname(7) we can see valid characters for hostnames are ASCII(7) letters from a to z, the digits from 0 to 9, and the hyphen (-). Since the underscore is invalid character in hostname, the system call
gethostbyname
will returnubuntuwork
and it is not listed in host table. The DNS resolution procedure will first query host table, if the query item is not found, system will continue to check thesearch
domain.
1 | ➜ hostname |
- By default, the search field in
/etc/resolv.conf
is empty but it can be configured with one or more search domains. After I check the/etc/resolv.conf
I findinternal.xxx
in the search field. That explains why there is a DNS resolution forubuntuwork.internal.xxx
. There is another question, why does the dns lookup for ano such name
host cost so much time?
1 | nameserver 127.0.0.53 |
For the third question, in order for sudo to know whether this rule should be applied, it needs to lookup the host it is running on. More details are explained in a stackoverflow answer sudo command trying to search for hostname.
Is there a DNS cache for linux server? The answer is no in OS-level unless a caching service such as Systemd-Resolved, DNSMasq, or Nscd is installed and running. In ubuntu 20.04 systemd-resolved is enabled by default, and I check the cached items by following commands. The
USR1
signal will not stop the service but tells systemd-resolved to write all the current cache entries (and some other information) to the system log. After checking the output file for cached items by searchingCACHE:
.ubuntuwork
is not in the cached items, which explains why thesudo
is slow each time.
1 | $ sudo killall -USR1 systemd-resolved |
Summary
After I have figured out the root cause, I find either of the following ways can workaround and make the sudo
run normally.
- Add an entry of
127.0.0.1 ubuntuwork
to/etc/hosts
- Remove the
search
line in/etc/resolv.conf
And actually, I should correct the hostname, such as renaming hostname from ubuntuwork
to ubuntu-work
and add corresponding entry to /etc/hosts
.