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 gethostbynamewill returnubuntuworkand 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 thesearchdomain.
| 1 | ➜ hostname | 
- By default, the search field in /etc/resolv.confis empty but it can be configured with one or more search domains. After I check the/etc/resolv.confI findinternal.xxxin 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 namehost 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 - USR1signal 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 searching- CACHE:.- ubuntuworkis not in the cached items, which explains why the- sudois 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 ubuntuworkto/etc/hosts
- Remove the searchline 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.