Macbook Air M1 terminal taking too much time to load [duplicate]
Short Answer:
The problem is caused by a (potentially) expensive ASL system log lookup. To see this in action, run sudo fs_usage | grep 'asl.*login'
in a Terminal window, then open a new Terminal window.
To solve the problem, configure Terminal to launch a non-standard shell:
- Create a symlink to your preferred shell. E.g.:
sudo ln -s /bin/bash /usr/local/bin/bash
- Open Terminal Preferences and select the "General" tab.
- Select "Shells open with: Command" and enter the symlink you created in step 1. E.g. "/usr/local/bin/bash".
Note 1: You may also need to add bash
and -bash
to the process list at "Terminal Preferences > Profiles > Shell > Ask before closing".
Note 2: /usr/local/bin
is writable in OS X 10.11 (El Capitan) Rootless mode.
To verify the fix:
- Open a new Terminal window.
- "Last Login:" should not be displayed at the top
- Open the inspector (Command + I) and select the Info tab.
- The command should read
login -pfq username /usr/bin/bash
orlogin -pfql username ...
Important: If the login command does not include the -q
parameter, then you have not fixed the problem.
You can also use sudo fs_usage | grep 'asl.*login'
to verify that /var/log/asl
is not accessed when opening a new Terminal window.
Details:
There are a number of bugs at play here.
The actual cause of the slowness is /usr/bin/login
, which by default will display the date of your last login. To get this last login date, it searches the ASL (Apple System Log) database at /var/log/asl/
. These log files can be very heavily fragmented and it's this file fragmentation that causes the delay when opening a new window or tab. (Bug 1)
The only way to suppress the ASL search for last login is to pass the -q
parameter to /usr/bin/login
. The .hushlogin
file will also suppress the "Last Login" display, but it does not suppress the expensive ASL search. (Bug 2)
Terminal always uses /usr/bin/login
to launch each new window/shell. There is no option to launch a shell directly nor is there a way to directly control the parameters passed to /usr/bin/login
(Bug 3).
As it turns out, Terminal will pass the -q
parameter to /usr/bin/login
when it is configured to use a non-standard shell. (Bug 4)
The -q
parameter is what we need to avoid the problem, hence the symlink to /usr/local/bin/bash
.
What I needed was changing from login shell to command /bin/bash -il
in iTerm's Preferences > Profiles > General > Command.
I needed the option -l
(Make bash act as if it had been invoked as a login shell) added in order to set environmental variables from ~/.bash_profile
.hushlogin
Create an empty file in your home folder called .hushlogin
; this will significantly decrease the time it takes for a Terminal.app tab to appear.
You can create the .hushlogin
file in Terminal.app using the following command:
touch ~/.hushlogin
The file will take effect immediately.
You can learn more about the .hushlogin
file and the login process in general in the login manual.
Quietening the login process
When you create a new Terminal tab, you are going through the login process. The process involves fetching various information about your previous login session, message of the day, and displaying system messages. This can be the source of significant delays. Try hushing these messages to see if the delay disappears.
OK I have a similar conclusion to Darren, though slightly different profiling mechanism (NB slow login can still occur in Yosemite).
Here's a way to tell what is actually running when you start a new login window, using the OS X sample profiler command.
Find out what command a normal login executs
$ ps -ef | grep login
You'll seee something like login -pfl username /bin/bash -c exec -la bash /bin/bash
Create a script file name profile_login.sh
with the following contents by adding a
-c ""
to the end of the discovered command to request that bash return immediately, with contents like this:
login -pfl username /bin/bash -c exec -la bash /bin/bash -c "" &
sudo sample $! -mayDie # sample the above command
Make it executable
$ chmod u+x profile_login.sh
and run it using sudo (sample
command requires it)
$ sudo ./profile_login.sh
OK so go ahead and run it. For instance by executing the purge
command first. On my box, I got a large output graph. Looking for the "biggest numbered branches" (typically at the top) I saw the following two biggest offenders:
One from something called pam_start
which appears to opening pam auth lib images
+ ! 1068 pam_start (in libpam.2.dylib) + 132 [0x7fff97295ab0]
+ ! : 1066 openpam_dynamic (in libpam.2.dylib) + 120 [0x7fff97293d14]
+ ! : | + ! 1042 coresymbolication_load_image(CSCppDyldSharedMemoryPage*, ImageLoader const*, unsigned long long) (in dyld) + 143 [0x7fff66725411]
+ ! : | + ! : 1042 mach_msg_trap (in dyld) + 10 [0x7fff6674a472]
and that is sometimes followed by another offender getlastlogxbyname
+ ! 583 getlastlogxbyname (in libsystem_c.dylib) + 212 [0x7fff92b3ef7a]
+ ! : 566 asl_file_open_read (in libsystem_asl.dylib) + 143 [0x7fff8c27030d]
+ ! : | 566 __open_nocancel (in libsystem_kernel.dylib) + 10 [0x7fff97b39012] + ! : | 566 __open_nocancel (in libsystem_kernel.dylib) + 10 [0x7fff97b39012]
So basically, there are two offenders. One is pam
(some type of authentication system) and the other it the asl
"detect your latest login" stuff. So apparently just deleting your /private/var/log/asl/*.asl
files is not enough. The pam loading is much more expensive on my machine, anyway [SSD]. Feel free to run the above script and see if your system is the same. Interestingly, the source code for these method calls seems to also be available online, for instance openpam_dynamic
If I follow Darren's answer, and replace my "shells open with" preference to something other than /bin/bash, I then see the following lines used to start new terminal tabs:
$ ps -ef | grep login
... login -pfql packrd /bin/bash -c exec -la bash /usr/bin/bash
So if I now use the same sample
trick on the new login command
login -pfql username /bin/bash -c exec -la bash /usr/bin/bash -c "" &
sudo sample $! -mayDie
a much smaller stacktrace is generated, the biggest offender being:
+ 8 pam_end (in libpam.2.dylib) + 190 [0x7fff97294ebb]
+ ! 6 coresymbolication_unload_image(CSCppDyldSharedMemoryPage*, ImageLoader const*) (in dyld) + 143 [0x7fff6e0f634f]
I think this is because the login "-q" parameter is now being used. Apparently this parameter skips both loading the pam modules and looking up the last login time (both offenders). According to the docs of the login
command, touching the ~/.hushlogin
file should do the same thing, but apparently this no longer works [at least for me with 10.10].
So, in summary, removing /private/var/log/asl/*.asl is not enough (in my experiment, it only accounted for at most 1/3 of the actual slowdown, though if you had mores files there it could account for a greater percentage I'm sure).
Anyway using similar scripts, you should be able to tell what's causing your local machine to bog down, and see if the above fix applies to you. Feel free to comment here.
UPDATE: seems that coresymbolication_load_image
can still take tons of time, even when login -pfql
is invoked (presumably some pam authentication module or other is having to "dial out" to a central login server or some odd, so has to wait for a response from a 3rd party). So the only real workaround I have found is to use iTerm2, and change the preferences -> profiles -> general -> Command to /bin/bash
instead.