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

前端 未结 3 1044
独厮守ぢ
独厮守ぢ 2020-12-08 11:07

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         


        
相关标签:
3条回答
  • 2020-12-08 11:49

    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.
    0 讨论(0)
  • launchd-oneshot is used to install script as a launchd job to run on login, with

    brew install cybertk/formulae/launchd-oneshot
    sudo launchd-oneshot Test.sh --on-login
    
    0 讨论(0)
  • 2020-12-08 12:12

    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

    0 讨论(0)
提交回复
热议问题