124

How can i speed up the terminal startup in Lion?

I'm not referring to the startup of the Terminal application, but to the startup terminal windows, like when i open a new tab.

I don't have anything in my .bash_profile file and i run rm -rf /private/var/log/asl/*.asl every 4 hours (which clear those files that usually make terminal slow ).

Currently, when i open a new tab, it takes 3-4 seconds until i can run something.

5
  • 2
    Perhaps there is something else wrong with your system? It shouldn't be that slow. Sometimes it takes a second or two for me, but usually it's only a split second. And I have a fair bit in .bash_profile (also check ~/.profile by the way). Also: note you can start typing while bash is loading, and usually what you type will be copied to the command prompt once it's ready. Commented Feb 26, 2012 at 0:44
  • Are you using a network account or a network home directory? Is Terminal responsive to user input while it's creating the terminal? Does it display the spinning busy cursor?
    – Chris Page
    Commented Feb 26, 2012 at 11:56
  • 1
    To find out where Terminal is spending the time, open Activity Monitor, select Terminal and click the Sample Process toolbar button, then immediately go to Terminal and create a new window/tab. The sample may provide a clue as to where the time is going. Also, watch the process list in Activity Monitor: if "login" or "bash" (or whatever shell you're using) appear in the list during the delay, that means the delay is likely occurring in one of those two programs and not Terminal.
    – Chris Page
    Commented Feb 26, 2012 at 11:58
  • Have you checked your PATH variable? I noticed that mine was absurdly long with many repeats due to some confusing .bashrc going-ons. I removed the repeats and everything sped up! Commented Mar 27, 2014 at 22:47
  • The cause is probably different for everyone, but for me the problem was my .bash_profile was calling homebrews $(brew --prefix coreutils) to append to the $PATH. This normally takes a second or so, but quite often would take up to 30 seconds for no apparent reason. I replaced this bit with a manually resolved path (/usr/local/opt/coreutils/libexec/gnubin) and have not had a problem since
    – carpii
    Commented Jan 3, 2021 at 20:28

11 Answers 11

118

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:

  1. Create a symlink to your preferred shell. E.g.: sudo ln -s /bin/bash /usr/local/bin/bash
  2. Open Terminal Preferences and select the "General" tab.
  3. 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 or login -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.

15
  • 6
    Do you know why -q is added if the command is a symlink to /bin/bash but not if it's /bin/bash?
    – Lri
    Commented Nov 18, 2012 at 15:16
  • 3
    @LauriRanta It seems to be a bug in the 10.7 and 10.8 Terminal. When the startup command is set to /bin/bash it behaves as if the Default Login Shell was selected. Any command other than /bin/bash will work correctly, so using /usr/bin/bash is just a workaround. This bug is not present in Snow Leopard.
    – Darren
    Commented Nov 18, 2012 at 15:34
  • 5
    @Darren have you reported this suspected bug to Apple? If not, please could you do so through: bugreport.apple.com Commented Dec 31, 2012 at 16:55
  • 3
    Unfortunate, this results in a promt about bash running every time you close the terminal on Yosemite. So not a nice fix :( Commented Dec 13, 2014 at 1:55
  • 2
    @ClausJørgensen I haven't experienced that problem. You may want to check the "Shell" settings under the Profiles tab.
    – Darren
    Commented Dec 13, 2014 at 2:01
28

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

6
  • 2
    Which stops the login search of ASL as per the accepted question
    – mmmmmm
    Commented Jul 11, 2015 at 12:25
  • 4
    out of all the solutions, this one worked for me. +50! Commented Aug 29, 2015 at 10:46
  • 2
    Great information all around in this thread! This is the solution I used because it didn't require creating symlinks or anything. My new shell startup times have gone from ~5-10seconds to instant with this solution.
    – DustinB
    Commented Nov 22, 2015 at 13:30
  • 1
    what should I do for the .zsh?
    – alper
    Commented May 10, 2020 at 20:00
  • 1
    @alper in principle -il also stands for 'interactive' and 'login' in zsh (as in bash) Commented Nov 3, 2020 at 10:04
21

.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.

2
  • 8
    .hushlogin does not actually solve the problem. This can be confirmed by using opensnoop. See my answer below.
    – Darren
    Commented Nov 18, 2012 at 11:47
  • 2
    @Darrren: man login tells me: -q This forces quiet logins, as if a .hushlogin is present. The q option is what you say prevents the issue, but it just does the same as with hushlogin.
    – Christian
    Commented Oct 13, 2015 at 17:15
11

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.

2
  • 3
    Apart from the ASL lookup, delays in login are most-often caused by being on a network with a directory server that is responding slowly when asked for your user info. If you're not on a network with directory services enabled, then I don't know what else would take significant time, other than general system congestion (CPU usage, memory pressure, I/O congestion).
    – Chris Page
    Commented Mar 20, 2015 at 3:38
  • @ChrisPage Yeah probably some network directory services something or other, good tip.
    – rogerdpack
    Commented Mar 20, 2015 at 16:56
3

It is all about investigating the cause. You can see what's being done while the process starts by inputing bash -x which will print out the process of starting up the shell.

Personally, I only notice the delay between activation and de-activation of the app and in the first tab created after a period of activity. It always makes me think that it is about memory pages being moved around.

3

In my case, after trying the above on my work machine without success, I found that the culprit was Active Directory. The fix was to go into Directory Utility and edit the AD service settings (double-click on "Active Directory") to enable "Create mobile account at login":

screenshot of Directory Utility application w/Active Directory settings open

This apparently causes the AD credentials to be cached locally, so the system no longer has to go out to the server every time it tries to validate your password.

You can get to Directory Utility with Spotlight or via the "Login Options" section of System Preferences / Users & Groups (select the "Edit…" button next to "Network Account Server"):

Users & Groups pane showing "Login Options" and "Edit…"

2

Reduce your history to something between 4 and 10 thousand lines and perhaps try quitting and discarding all saved windows. I have seen both make a difference on slower machines - especially ones without SSD for storage.

2

For those with with slow startup times but none of the above work,
my .zprofile was littered with eval "$(/opt/homebrew/bin/brew shellenv)" repeated 50x.
So profiling was giving me super fast speeds and the terminal took 4 to 10 seconds to load.
You can access this file at ~/.zprofile\

Remove all the lines and it'll immediately be an instant prompt again. Good luck!

0
0

Just run:

sudo creatbyproc.d
sudo newproc.d

in separate terminals and open the new open to see what is being executed during that time.

If nothing obvious, try the following:

sudo dtruss -an Terminal

This will print all your details which are happening on tab loading time.

0

Open /etc/profile and add the line PATH="" so it looks like this:

if [ -x /usr/libexec/path_helper ]; then
    PATH=""
    eval `/usr/libexec/path_helper -s`
fi
0

The problem for me was that the active directory domain server was invalid.

Changing it then rebooting the mac fixed it.

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .