Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Launch shell script on login in Mac OS (OS X)

Tags:

bash

shell

macos

I have this shell script Test.sh:

#! /bin/bash

FILE_TO_CHECK="/Users/test/start.txt"
EXIT=0

while [ $EXIT -eq 0 ]; do
    if [ -f "$FILE_TO_CHECK" ]
        then
        /usr/bin/java -jar myapp.jar
        EXIT=1
    else
        sleep 30
    fi
done

I need to start this script automatically after login.
So I put it inside a folder Test in /System/Library/StartupItems/

When I reboot the Mac, nothing happens after I log in. Any clue?

I also tried Automator, but with the same result: the java program is not running.

like image 715
user3472065 Avatar asked Apr 03 '14 15:04

user3472065


People also ask

How do I run a login script on Mac?

In the Script Editor app on your Mac, click the Run button in the toolbar, or press Command-R, to execute the commands in your script.

Can we run shell script in Mac Terminal?

Instead of entering commands and waiting for a response, you can compose shell scripts that run without direct interaction. A shell script is a text file that contains one or more UNIX commands.

Where are startup scripts on a Mac?

System startup scripts go into one of the /etc/mach_init*. d directories. Bootstrap service daemons are identified to the system by using the ServiceName key in their . plist files.


2 Answers

Ivan Kovacevic's pointers, especially the superuser.com link, are helpful; since at least OS X 10.9.2, your options for creating run-at-login scripts are:

Note: The methods are annotated with respect to whether they are:

  • specific to a given user ("[user-SPECIFIC]"); i.e., the installation must be performed for each user, if desired; scripts are typically stored in a user-specific location, and root (administrative) privileges are NOT required for installation.
  • effective for ALL users ("[ALL users]"); i.e., the installation takes effect for ALL users; scripts are typically stored in a shared location and root (administrative) privileges ARE required for installation.

The scripts themselves will run invisibly, but - with the exception of the com.apple.loginwindow login-hook method - you can open applications visibly from them; things to note:

  • There is no guarantee that any such application will be frontmost, so it may be obscured by other windows opened during login.

  • If you want to run another shell script visibly, simply use open /path/to/your-script, which will open it in Terminal.app; however, the Terminal window will automatically close when your script terminates.


Automator [user-SPECIFIC]:

  • File > New, type Application
  • Add a Run Shell Script action, which adds an embedded bash script, and either paste your script code there or add a command that invokes an existing script from there.
  • Save the *.app bundle and add it to the Login Items list in System Preferences > User & Groups > Login Items.

    Note:

    • The embedded script runs with the default "C" locale.
    • $PATH is fixed to /usr/bin:/bin:/usr/sbin:/sbin, which notably does NOT include /usr/local/bin
    • The working dir. is the current user's home directory.

com.apple.loginwindowlogin hook [ALL users - DEPRECATED, but still works]:

If you have admin privileges, this is the easiest method, but it is DEPRECATED, for a variety of reasons (security, limited to a single, shared script, synchronous execution); Apple especially cautions against use of this mechanism as part of a software product.

  • Place your script, e.g., Test.sh, in a shared location - e.g., /Users/Shared - and make sure it is executable (chmod +x /Users/Shared/Test.sh).
  • From Terminal.app, run the following:

    sudo defaults write com.apple.loginwindow LoginHook /Users/Shared/Test.sh

  • Note:

    • The script will run as the root user, so exercise due caution.
      Among the methods listed here, this is the only way to run a script as root.

    • There's only one system-wide login hook.

      • Note that there's also a log-OUT hook, LogoutHook, which provides run-at-logout functionality - unlike the other approaches.
    • The login-hook script runs synchronously before other login actions, and should therefore be kept short.

      • Notably, it runs before the desktop is displayed; you cannot launch applications from the script, but you can create simple interactions via osascript and AppleScript snippets (e.g., osascript -e 'display dialog "Proceed?"'); however, any interactions block the login process.
    • The script runs in the context of the root user and he username of the user logging on is passed as the 1st argument to the script.

    • The script runs with the default "C" locale.
    • $PATH is fixed to /usr/bin:/bin:/usr/sbin:/sbin, which notably does NOT include /usr/local/bin
    • The working dir. is /.

launchd agents:

launchd-agent-executed scripts can be installed for a SPECIFIC user OR for ALL users - the latter requires administrative privileges.

While using launchd is Apple's preferred method, it's also the most cumbersome, as it requires creating a separate *.plist configuration file.
On the upside, you can install multiple scripts independently.

  • Note:
    • No specific timing or sequencing of launchd scripts is guaranteed; loosely speaking, they "run at the same time at login"; there is even no guaranteed timing between the user-specific and the all-user tasks.
    • The script runs with the default "C" locale.
    • $PATH is fixed to /usr/bin:/bin:/usr/sbin:/sbin, which notably does NOT include /usr/local/bin
    • The working dir. is / by default, but you can configure it via the .plist file - see below.
    • The script-file path must be specified as a full, literal path (e.g., /Users/jdoe/script.sh; notably , ~-prefixed paths do not work.
    • For a description of all keys that can be used in *.plist configuration files, see man launchd.plist.
    • Both user-specific and all-users tasks run as the current user (the user logging on).

launchd [user-SPECIFIC]:

  • Note: Lingon 3 ($5 as of early 2014) is a GUI application that facilitates the process below, but only for user-specific scripts.
  • Place your script, e.g., Test.sh, in your home folder, e.g., /Users/jdoe
  • Create a file with extension .plist in ~/Library/LaunchAgents, e.g., ~/Library/LaunchAgents/LoginScripts.Test.plist, by running the following in Terminal.app:

    touch ~/Library/LaunchAgents/LoginScripts.Test.plist
    
  • Open the file and save it with the following content:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>Label</key>
          <!-- YOUR SELF-CHOSEN *UNIQUE* LABEL (TASK ID) HERE -->
        <string>LoginScripts.Test.sh</string>
        <key>ProgramArguments</key>
        <array>
              <!-- YOUR *FULL, LITERAL* SCRIPT PATH HERE -->
            <string>/Users/jdoe/Test.sh</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
    </dict>
    </plist>
    
  • The <!-- ... --> comments indicate the places to customize; you're free to choose a label, but it should be unique - ditto for the .plist filename; for simplicity, keep the label and the filename root the same.

  • From Terminal.app, run the following:

    launchctl load ~/Library/LaunchAgents/LoginScripts.Test.plist
    
  • Note that, as a side effect, the script will execute right away. From that point on, the script will execute whenever the CURRENT user logs on.

  • It is not strictly necessary to run launchctl load -- since, by virtue of the file's location, it will be picked up automatically on next login -- but it's helpful for verifying that the file loads correctly.

launchd [ALL users]

  • Place your script, e.g., Test.sh, in a SHARED location, e.g., /Users/Shared
  • Create a file with extension .plist in /Library/LaunchAgents (requires admin privileges), e.g., /Library/LaunchAgents/LoginScripts.Test.plist, by running the following in Terminal.app:

    sudo touch /Library/LaunchAgents/LoginScripts.Test.plist
    
  • Open the file and save it with the following content (make sure your text editor prompts for admin privileges on demand; alternatively, use sudo nano /Library/LaunchAgents/LoginScripts.Test.plist):

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>Label</key>
          <!-- YOUR SELF-CHOSEN *UNIQUE* LABEL (TASK ID) HERE -->
        <string>LoginScripts.Test.sh</string>
        <key>ProgramArguments</key>
        <array>
              <!-- YOUR *FULL, LITERAL* SCRIPT PATH HERE -->
            <string>/Users/Shared/Test.sh</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
    </dict>
    </plist>
    
  • The <!-- ... --> comments indicate the places to customize; you're free to choose a label, but it should be unique - ditto for the .plist filename; for simplicity, keep the label and the filename root the same.

  • From Terminal.app, run the following:

    sudo chown root /Library/LaunchAgents/LoginScripts.Test.plist
    sudo launchctl load /Library/LaunchAgents/LoginScripts.Test.plist
    
  • Note that, as a side effect, the script will execute right away. From that point on, the script will execute whenever ANY user logs on.

  • It is not strictly necessary to run launchctl load -- since, by virtue of the file's location, it will be picked up automatically on next login -- but it's helpful for verifying that the file loads correctly.
like image 175
mklement0 Avatar answered Nov 16 '22 01:11

mklement0


You can't just place plain scripts in that folder. You need a "specialized bundle" how Apple calls it, basically a folder with your executable, and a .plist configuration. And you should put it in /Library/StartupItems since /System/Library/StartupItems/ is reserved for the operating system. Read all about it here:

https://developer.apple.com/library/mac/documentation/macosx/conceptual/bpsystemstartup/chapters/StartupItems.html

Also note that the whole stuff is marked as deprecated technology. And that Apple is suggesting the use of launchd. There is an example how to set it up here:

https://superuser.com/questions/229773/run-command-on-startup-login-mac-os-x

like image 37
Ivan Kovacevic Avatar answered Nov 15 '22 23:11

Ivan Kovacevic



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!