Setting environment variables (specifically the PYTHON PATH) on a mac - macos

Because it was such a mission to get this simple bit of info I've decided to post it for others:
In terminal execute: mkdir ~/.MacOSX
In terminal execute: touch ~/.MacOSX/environment.plist
Browse to the file and open.
Paste:
<key>DISPLAY</key>
<string>:0.0</string>
<key>PYTHONPATH</key>
<string>/full/path/ofyour/favorite/script/dir:/full/path/of/another/script/dir:
Edit to what you need and save.

Here is the documented way to do it with Property List Editor.
Note that you should use caution when setting environment variables this way as they apply to launched GUI applications which might not be expecting them. For setting default environment variables when working in a terminal shell, the conventional UNIX way of using shell profile commands, like .profile or .bash_profile is preferred and less likely to break things.

In terminal execute: mkdir ~/.MacOSX
In terminal execute: touch ~/.MacOSX/environment.plist
Browse to the file and open.
Paste:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>DISPLAY</key>
<string>:0.0</string>
<key>PYTHONPATH</key>
<string>/full/path/ofyour/favorite/script/dir:/full/path/of/another/script/dir:</string>
</dict>
</plist>
Edit to what you need and save.
(This was written by the original poster as part of the question. Reposted as community wiki because I didn't write it, just cleaned up the formatting.)

Related

Run Python Script at OS X Startup

I am very new to python as well as MAC OSX. For my academic project I need to download a bunch of tweets from twitter using twitter streaming API. I need to download atleast 5000000 tweets. So I have written a python script and placed it in start-up. "System Preference -> Users and Groups -> Login items" and added my script there. But I see that the script is not executed when I login to the system ! Please help me resolve this issue.
Adapt the following accordingly, name it something like myscript_launcher.plist, and put it in either one of three locations: /System/Library/LaunchAgents, /System/Library/LaunchDaemons, /Users/<username>/Library/LaunchAgents.
<?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>
<string>my.python.script.name</string>
<key>ProgramArguments</key>
<array>
<string>/path/to/python</string>
<string>/path/to/python/script.py</string>
</array>
<key>StandardErrorPath</key>
<string>/var/log/python_script.error</string>
<key>KeepAlive</key>
<true/>
</dict>
</plist>
Also, let's assume you put the plist file in ~/Library/LaunchAgents. You can start and stop it with the launchctl. To start, use launchctl load ~/Library/LaunchAgents/myscript_launcher.plist. To stop it, do the same but use the unload argument
You need to create a shell file that launches your python code. Tell the shell script to start at log in.
example
#!/bin/bash
python username/Desktop/startupscripts/file.py
save the file with the .sh extension.
add the .sh file to
"System Preference -> Users and Groups -> Login items", the .sh script will call the python file.
This is what you should have in the shell file. I'm assume this is the path to the file, if it isn't modify it.
#!/bin/bash
python /Users/username/moviebuzz-api/flask/bin/streaming_movies.py
nothing else.
Here's the full solution I am using on Mojave:
Plist: ~/Library/LaunchAgents/play.with.mpv.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>Disabled</key>
<false/>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/Users/e/Library/Python/3.7/bin:/usr/local/bin</string>
</dict>
<key>KeepAlive</key>
<true/>
<key>Label</key>
<string>play.with.mpv</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/python3</string>
<string>/Users/e/Library/Python/3.7/bin/play-with-mpv</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>StandardErrorPath</key>
<string>/tmp/play.with.mpv.stderr</string>
<key>StandardOutPath</key>
<string>/tmp/play.with.mpv.stdout</string>
</dict>
</plist>
Mind the PATH to python3 - find it with which python3 and the play-with-mpv python script!
Load plist:
launchctl load ~/Library/LaunchAgents/play.with.mpv.plist
If your video is dropping frames as hell, create mpv config in ~/.config/mpv/mpv.conf and put there this:
video-sync=display-resample
if that do doesn't help, try this instead
opengl-early-flush=no
But I see that the script is not executed when I login to the system !
The problem is, .py files are usually opened by some text editor by default. In order to execute the script as Login Items, you need to make the script to be opened by Terminal.app (or anything execute the script) by default.
After that, you cat set the script as Login Items in the way you posted.
How to set Terminal.app as default:
Put a #! line on the top of the script:
#!/usr/bin/env python3
print("hello world")
Add execute permission to the script:
chmod u+x script.py
Change the file extension .py to .command (to associate the file with Terminal.app):
mv script.py script.command
At this point, you should be able to run the script by double clicking on Finder.
If you can not, try the following:
Right click on the script file on Finder.
Select Get Info
Click the dropdown of Open with: option.
Select Terminal.app
By the way, the above applies to not only python, but other scripts such as bash.
For example of bash, change !# like so:
#!/usr/bin/env bash

Set metadata field on file

I have a PDF file. If I look at the Get Info window, the Title under More Info is "Title1". I am trying to set this value using terminal so I can eventually turn it into an applescript.
See Stackoverflow question Mac OS X : add a custom meta data field to any file
I used the answer from Anderson Freitas to correctly set an author by using the command"
xattr -wx "com.apple.metadata:kMDItemAuthors" "`xxd -ps author.plist`" "Put File Name Here.pdf"
However, if I replace kMDItemAuthors with mMDItemTitle, the command runs without error, but no changes are seen in the title either by looking at Get Info or by using mdls on the command line.
The contents of my title.plist file is:
<?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">
<string>Title2</string>
</plist>
The actual command I run to set the title is:
xattr -wx "com.apple.metadata:kMDItemTitle" "`xxd -ps title.plist`" "Put File Name Here.pdf"
Any thoughts where I might be doing something wrong?

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

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.
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.
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
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
Disclosure: I am the author of this package.

Run applescript in Automator

I need to start and stop a small server with automator but my knoledge is very limited. I can't manage to set the path where the file is and I don't know how to stop the server.
So far I have this:
on run
set r to display dialog "Start or stop the NINJAM server ?" buttons {"Stop", "Start"}
if button returned of r is "Start" then
#tell application "Terminal"
# activate
do shell script "cd \"/Applications/ MUSIC/ Utilities/Audio IP/NINJAM/NINJAM/NinjamOSXServer ./ninjamsrv Server.cfg\""
#end tell
else
do shell script "Stop"
end if
end run
Any help is really apprectated. Thanks in advance.
NOTE that I'm using my own path here -- I put the ninjam server folder in the top level of my Applications folder.
I had to create a 'term' file, which is a text file with this in it:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>WindowSettings</key>
<array>
<dict>
<key>ExecutionString</key>
<string>cd /Applications/NinjamOSXServer/;./ninjamsrv config.cfg</string>
</dict>
</array>
</dict>
</plist>
I saved this as LaunchNinjamSrvr.term and put it in the same folder as the ninjamsrvr. Then the script to use is:
set r to display dialog "Start or stop the NINJAM server ?" buttons {"Stop", "Start"}
if button returned of r is "Start" then
do shell script "open /Applications/NinjamOSXServer/LaunchNinjamSrvr.term"
else
do shell script "killall -INT -v ninjamsrv"
end if
[Occurs to me that I should give some explanation. Directly using the full path with the " config.cfg" parameter makes 'do shell script' choke. Splitting into two commands (but still using do shell script), like you see in the .term file, works to launch ninjamsrv, but makes the script editor (I use Smile) freeze. So that is (presumably -- I didn't want to test it by other means [script app, etc.]) a problem, and why I resorted to using the .term file. It used to be that you could, from the File menu in Terminal (as I recall), save a .term file directly, but that seems to have fallen by the way-side. So, at this point, I have a template that I use and just paste commands into the appropriate line. (But see http://discussions.apple.com/thread/3139585?start=0&tstart=0 -- wherein the technique of exporting Terminal Preference file is explained). I'm being a bit lazy in that the new form is .terminal, not .term ... anyway ...
So now all that is left is doing the actual AS script. 'open' is a basic command line command which is just like opening or double-clicking in the Finder. If, for some reason your file opens in the wrong app or doesn't open, you might need to map it to Terminal.app (in the get info window) and/or change the extension to the more up--to-date '.terminal'.
killall is like kill, designed to kill processes in various ways. I chose -INT because this is essentially like doing a control-c to interrupt the process.]

How do I make the dock icon stop bouncing after my app wrapper script starts?

So I recently made an .app wrapper for a zsh script, but when I run it, the icon for the app keeps hopping in the Dock.
The app is basically:
% find Example.app -type f
Example.app/Contents/Info.plist
Example.app/Contents/MacOS/wrapper.sh
% cat Example.app/Contents/Info.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- tell OSX what the name of the executable is -->
<key>CFBundleExecutable</key>
<string>wrapper.sh</string>
</dict>
</plist>
% cat Example.app/Contents/MacOS/wrapper.sh
#!/usr/bin/env zsh
# not my real script, but something else that hangs for a while
sleep 10
%
You can also grab it from github.
Is there any way I can get the app icon to stop hopping, and act like a normal app, and just sit there
with a triangle next to it?
An application's icon will bounce in the OS X Dock until the app enters its main event loop and begins responding to user input. As your script probably doesn't run a Carbon or Cocoa event loop (See documentation for Carbon Event Manager and NSApplication, respectively), the Dock is waiting continuously, expecting a regular foreground GUI application to emerge.
A script-wrapping tool that I've had success with is Platypus. It can run its own event loop while executing your script, and do a number of other convenient things.
You want DropScript. The dock doesn't work with shell scripts like that, it expects something a bit more full-fledged.
I think if you add LSUIElement to your Info.plist file, it should work.

Resources