itoutline.me

 

Zmienne systemowe w OSX

Definiowanie zmiennych systemowych w OSX jest takie sobie… Nie mówię tutaj o zmiennych, które można ustawić w plikach inicjalizacyjnych powłoki shellowej (bash, zsh, fish czy co komu odpowiada). Tam akurat wszystko jest całkiem prosto ale o ustawieniu zmiennej bez uruchamiania terminala po starcie systemu. Natrafiłem na potrzebę zdefiniowania takiej zmiennej przy zabawie z Android Studio. Po zainstalowaniu Javy i wspomnianego oprogramowania, próba jego uruchomienia kończyła się tak:

Problemem okazał się brak zmiennej STUDIO_JDK. Można ten problem obejść np. tak:

launchctl setenv STUDIO_JDK /Library/Java/JavaVirtualMachines/jdk1.8.0_25.jdk
open /Applications/Android\ Studio.app

Tylko, że jakoś konieczność uruchomienia terminala po to, żeby pracować w aplikacji graficznej do mnie nie przemawia. Udało mi się znaleźć ciekawe rozwiązanie problemu tutaj.

Zmienne systemowe

Zmienne mogą być ustawione na poziomie użytkownika (ustawienie wywoływane przez /Library/LaunchAgents/environment.user.plist) lub root-a (/Library/LaunchDaemons/environment.plist). Rozwiązanie zakłada jeden plik w którym będą definiowane zmienne /etc/environment, co jest bardzo ok bo nie przypominam sobie, żebym kiedyś potrzebował różnych. Kolejnym plusem jest fakt, że modyfikacja /etc/environment czyli dodanie jakiejś zmiennej automatycznie jest zaczytywane i dostajemy wzrokową informację w postaci chwilowego zniknięcia Dock-a.

Jedyny minus ale to jest raczej nie do obejścia to fakt, że już działająca aplikacja nie pobierze informacji o nowej zmiennej, musi być ponownie otworzona.

Zmienna PATH

To rozwiązanie jest jeszcze lepsze i dopóki będzie działało na OSX to będę z niego korzystał a mianowicie zmiany dokonujemy w pliku /etc/paths. To zwykły plik tekstowy w którym możemy dodawać kolejne linijki z wymaganymi przez nas ścieżkami. Po ponownym uruchomieniu terminala dopisana przez nas ścieżka znajdzie się w zmiennej PATH.

Ostatecznie

Przygotowałem skrypt bashowy, który tworze niezbędne pliki i ustawia ich parametry.

(set_env_var.sh) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#!/usr/bin/env bash

sudo -v

cat << EOF | sudo tee /etc/environment > /dev/null
#!/bin/sh

set -e

syslog -s -l warn "Set environment variables with /etc/environment $(whoami) - start"


### Set your variable here:
#launchctl setenv JAVA_HOME      /usr/local/jdk1.7
launchctl setenv MAVEN_HOME     /opt/local/share/java/maven3
launchctl setenv STUDIO_JDK     /Library/Java/JavaVirtualMachines/jdk1.8.0_25.jdk
############################

if [ -x /usr/libexec/path_helper ]; then
        export PATH=""
            eval `/usr/libexec/path_helper -s`
                launchctl setenv PATH $PATH
            fi

            osascript -e 'tell app "Dock" to quit'

            syslog -s -l warn "Set environment variables with /etc/environment $(whoami) - complete"
EOF

cat << EOF | sudo tee /Library/LaunchAgents/environment.user.plist > /dev/null
<?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>environment.user</string>
    <key>ProgramArguments</key>
    <array>
            <string>/etc/environment</string>
    </array>
    <key>KeepAlive</key>
    <false/>
    <key>RunAtLoad</key>
    <true/>
    <key>WatchPaths</key>
    <array>
        <string>/etc/environment</string>
    </array>
</dict>
</plist>
EOF

cat << EOF | sudo tee /Library/LaunchDaemons/environment.plist > /dev/null
<?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>environment</string>
    <key>ProgramArguments</key>
    <array>
            <string>/etc/environment</string>
    </array>
    <key>KeepAlive</key>
    <false/>
    <key>RunAtLoad</key>
    <true/>
    <key>WatchPaths</key>
    <array>
        <string>/etc/environment</string>
    </array>
</dict>
</plist>
EOF

sudo chmod 555 /etc/environment
sudo chmod 600 /Library/LaunchAgents/environment.user.plist /Library/LaunchDaemons/environment.plist
sudo chown root:wheel /etc/environment /Library/LaunchAgents/environment.user.plist /Library/LaunchDaemons/environment.plist

launchctl load -w /Library/LaunchAgents/environment.user.plist
sudo launchctl load -w /Library/LaunchDaemons/environment.plist

Zastosowanie rozwiązania:

wget http://itoutline.me/code/set_env_var.sh
chmod +x set_env_var.sh
./set_env_var.sh

Od tej pory zdefiniowanie jakiejkolwiek zmiennej, która będzie zawsze i wszędzie widoczna to umieszczenie jej w /etc/environment.

Pożyteczne komendy

Ustawienie zmiennej z poziomu terminala (będzie od razu widoczne w systemie ale na liście zmiennych wyświetlanej np. za pomocą env czy echo $STUDIO_JDK pojawi się dopiero po restarcie terminala:

launchctl setenv STUDIO_JDK /Library/Java/JavaVirtualMachines/jdk1.8.0_25.jdk

Sprawdzenie zmiennej w systemie:

launchctl getenv STUDIO_JDK /Library/Java/JavaVirtualMachines/jdk1.8.0_25.jdk

Sprawdzenie czy zmienna jest już widoczna w sesji terminala:

echo $STUDIO_JDK

Wyświetlenie wszystkich zmiennych widocznych z poziomu terminala:

env

Ustawienie zmiennej tylko na poziomie terminala:

export STUDIO_JDK=/Library/Java/JavaVirtualMachines/jdk1.8.0_25.jdk

Comments