Mengatur variabel lingkungan melalui launchd.conf tidak lagi berfungsi di OS X Yosemite / El Capitan / macOS Sierra / Mojave?

190

Sepertinya launchd.conftidak memuat variabel lingkungan saya lagi. Adakah orang lain yang memperhatikan hal itu?

Apakah ada solusi lain untuk menetapkan variabel lingkungan secara permanen?

Omong kosong
sumber
Itu berfungsi dan membuatnya tersedia dalam aplikasi tetapi tidak di terminal
Chang Zhao

Jawaban:

159

Buat environment.plistfile ~/Library/LaunchAgents/dengan konten ini:

<?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.startup</string>
  <key>ProgramArguments</key>
  <array>
    <string>sh</string>
    <string>-c</string>
    <string>
    launchctl setenv PRODUCTS_PATH /Users/mortimer/Projects/my_products
    launchctl setenv ANDROID_NDK_HOME /Applications/android-ndk
    launchctl setenv PATH $PATH:/Applications/gradle/bin
    </string>

  </array>
  <key>RunAtLoad</key>
  <true/>
</dict>
</plist>

Anda dapat menambahkan banyak launchctlperintah di dalam <string></string>blokir.

The plistakan mengaktifkan setelah sistem reboot. Anda juga dapat menggunakannya launchctl load ~/Library/LaunchAgents/environment.plistuntuk segera meluncurkannya.

[Sunting]

Solusi yang sama juga berfungsi di El Capitan.

Xcode 7.0+ tidak mengevaluasi variabel lingkungan secara default. Perilaku lama dapat diaktifkan dengan perintah ini:

defaults write com.apple.dt.Xcode UseSanitizedBuildSystemEnvironment -bool NO

[Sunting]

Ada beberapa situasi di mana ini tidak berhasil. Jika komputer dihidupkan ulang dan "Buka kembali jendela saat masuk kembali" dipilih, jendela yang dibuka kembali mungkin tidak melihat variabel (Mungkin mereka dibuka sebelum agen dijalankan). Juga, jika Anda masuk melalui ssh, variabel tidak akan ditetapkan (jadi Anda harus mengaturnya di ~ / .bash_profile). Akhirnya, ini tampaknya tidak berhasil untuk PATH di El Capitan dan Sierra. Itu perlu diatur melalui 'luncurkan pengguna config config ...' dan di / etc / paths.

MortimerGoro
sumber
20
Tidak perlu reboot! Anda dapat melakukan "launchctl start environment.plist" dan restart aplikasi yang Anda perlukan untuk mendapatkan env vars baru;)
hasvn
1
Ini tidak akan berfungsi dengan variabel PATH untuk saya. Jadi selain pendekatan ini untuk mengatur variabel lain, saya mengatur variabel PATH di ~ / .bash_profile saya. Ini mungkin tidak bekerja untuk setiap kasus tetapi sejauh ini saya tidak punya masalah.
djule5
6
Mencari tahu: Untuk bekerja tanpa reboot, itu harus "launchctl load environment.plist", jangan mulai
Dave Hartnoll
2
Ah iya. Tidak ada yang seperti pengaturan konfigurasi yang tidak jelas yang muncul tepat 9 kali di seluruh internet (google UseSanitizedBuildSystemEnvironment).
Ohad Schneider
2
Bekerja di Sierra juga
Shwouchk
64

[ Jawaban asli ]: Anda masih dapat menggunakan launchctl setenv variablename valueuntuk mengatur variabel sehingga diambil oleh semua aplikasi (aplikasi grafis dimulai melalui Dock atau Spotlight, selain yang dimulai melalui terminal).

Tentunya Anda tidak akan ingin melakukan ini setiap kali Anda masuk.

[ Sunting ]: Untuk menghindari ini, luncurkan AppleScript Editor, masukkan perintah seperti ini:

do shell script "launchctl setenv variablename value"

(Gunakan beberapa baris jika Anda ingin mengatur beberapa variabel)

Sekarang simpan ( + s) sebagai format File: Aplikasi . Terakhir buka System SettingsPengguna & GrupItem Login dan tambahkan aplikasi baru Anda.

[ Jawaban asli ]: Untuk mengatasi semua variabel yang ingin Anda tentukan dalam skrip shell pendek, lihat jawaban sebelumnya tentang cara menjalankan skrip pada login MacOS . Dengan begitu skrip akan dipanggil saat pengguna masuk.

[ Sunting ]: Tidak ada solusi yang sempurna karena variabel hanya akan ditetapkan untuk spesifik itu pengguna tetapi saya berharap / menebak itu mungkin yang Anda butuhkan.

Jika Anda memiliki banyak pengguna, Anda bisa secara manual mengatur Item Login untuk masing-masing dari mereka atau menempatkan salinan com.user.loginscript.plist di masing-masing Perpustakaan / LaunchAgents lokal mereka direktori , menunjuk pada skrip shell yang sama.

Memang, tak satu pun dari solusi ini senyaman /etc/launchd.conf .

[ Edit Lebih Lanjut ]: Seorang pengguna di bawah ini menyebutkan bahwa ini tidak berhasil untuknya. Namun saya telah menguji beberapa mesin Yosemite dan tidak berfungsi untuk saya. Jika Anda mengalami masalah, ingatlah bahwa Anda harus memulai ulang aplikasi agar ini dapat berlaku. Selain itu jika Anda menetapkan variabel di terminal melalui ~ / .profile atau ~ / .bash_profile , mereka akan menimpa hal-hal yang ditetapkan melalui launchctl setenv untuk aplikasi yang dimulai dari shell .

ruario
sumber
5
Sejauh yang saya tahu, satu kelemahan dari teknik ini adalah bahwa variabel tidak akan ditetapkan untuk aplikasi lain yang dimulai saat login. Jadi misalnya jika Anda membuka Terminal, variabel akan ditetapkan, tetapi jika Anda log off dan kembali lagi, memiliki Terminal secara otomatis restart, variabel akan tidak disetel ...
JasonD
Saya sudah mencoba solusi ini dan tidak berhasil juga. Tapi saya secara khusus mengharapkan Java IDE (IntelliJ) saya untuk mengambil modifikasi jalur saya dan ternyata tidak. Semuanya bekerja dengan baik dari terminal. Mungkin ada bug di IntelliJ. Masih frustasi karena Apple menghapus fungsi ini. Saya menelepon Apple dan mereka tidak terlalu membantu.
Jason
Ini berfungsi untuk saya, tetapi apakah Anda tahu apa yang harus dilakukan untuk juga menambahkan variabel lingkungan ke sudo?
etiennenoel
2
Ini akan berfungsi secara umum, namun ada bug di Yosemite (setidaknya 10.10.0 dan 10.10.1) di mana pengaturan $ PATH tidak berfungsi seperti ini. Apple mengetahui bug tersebut. Saat ini (pada 10.10.1) tidak ada cara yang diketahui untuk menetapkan $ PATH seluruh sistem untuk aplikasi GUI.
TJ Luoma
3
Setelah Anda menggunakan salah satu metode yang disebutkan di atas dan reboot laptop Anda - Pastikan Anda secara eksplisit membuka kembali aplikasi (seperti iTerm, terminal, Eclipse, IDEA atau apa pun yang Anda gunakan). Jika Anda tidak secara eksplisit me-restart mereka dan Jika saat me-reboot OSx kotak centang diperiksa untuk "Restart windows ketika masuk kembali" (yang merupakan default) - program-program tersebut tidak akan membaca variabel lingkungan yang baru.
Ran
21

Dimungkinkan untuk mengatur variabel lingkungan pada Mac OS X 10.10 Yosemite dengan 3 file + 2 perintah.

File utama dengan definisi variabel lingkungan:

$ ls -la /etc/environment 
-r-xr-xr-x  1 root  wheel  369 Oct 21 04:42 /etc/environment
$ cat /etc/environment
#!/bin/sh

set -e

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

launchctl setenv JAVA_HOME      /usr/local/jdk1.7
launchctl setenv MAVEN_HOME     /opt/local/share/java/maven3

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"

Definisi layanan untuk memuat variabel lingkungan untuk aplikasi pengguna (terminal, IDE, ...):

$ ls -la /Library/LaunchAgents/environment.user.plist
-rw-------  1 root  wheel  504 Oct 21 04:37 /Library/LaunchAgents/environment.user.plist
$ sudo cat /Library/LaunchAgents/environment.user.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>
    <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>

Definisi layanan yang sama untuk aplikasi pengguna root:

$ ls -la /Library/LaunchDaemons/environment.plist
-rw-------  1 root  wheel  499 Oct 21 04:38 /Library/LaunchDaemons/environment.plist
$ sudo cat /Library/LaunchDaemons/environment.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>
    <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>

Dan akhirnya kita harus mendaftarkan layanan ini:

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

Apa yang kita dapatkan:

  1. Satu-satunya tempat untuk mendeklarasikan variabel lingkungan sistem: / etc / environment
  2. Pembaruan otomatis variabel lingkungan instan setelah modifikasi file / etc / environment - jalankan ulang aplikasi Anda

Masalah / masalah:

Agar variabel env Anda diambil dengan benar oleh aplikasi setelah sistem dinyalakan ulang, Anda perlu:

  • masuk baik dua kali: login => logout => login
  • atau tutup & buka kembali aplikasi secara manual, di mana variabel env harus diambil
  • atau JANGAN menggunakan fitur "Buka kembali jendela saat masuk kembali".

Ini terjadi karena Apple menolak pemesanan eksplisit layanan yang dimuat, sehingga variabel env terdaftar secara paralel dengan pemrosesan "buka kembali antrian".

Tapi sebenarnya, saya reboot sistem saya hanya beberapa kali per tahun (pada pembaruan besar), jadi itu bukan masalah besar.

ursa
sumber
Ide yang hebat. Saya telah mencobanya dan berfungsi untuk sebagian besar variabel lingkungan (seperti JAVA_HOME), tetapi tidak untuk PATHvariabelnya (lihat pertanyaan saya tentang bertanya berbeda ).
halloleo
4
PATH harus diset dengan file / etc / paths. Tambahkan saja jalur kustom Anda ke akhir file ini.
ursa
Saya tidak terlalu familiar dengan itu launchd, tetapi bukankah mungkin untuk memuat Daemon tersebut saat boot (yaitu sebelum masuk)? Itu harus menghindari semua masalah yang Anda sebutkan.
Egon
Saya suka pendekatan di atas tetapi memiliki masalah aneh untuk dikelola. Setelah reboot, gen VARNAME mengembalikan saya nilai yang benar tetapi echo $ VARNAME tidak menghasilkan apa-apa. Apa yang mungkin menjadi alasan untuk ini? Saya mempostingnya ke stackoverflow.com/questions/27045137/… juga dan berharap ada orang di sini yang punya ide
ctp
Pastikan izin file dari / etc / environment seperti dijelaskan di atas.
imanuelcostigan
6

Dikutip dari

Apple Developer Relations 10-Oct-2014 09:12 PM

Setelah banyak pertimbangan, teknik telah menghapus fitur ini. File /etc/launchd.confitu sengaja dihapus karena alasan keamanan. Sebagai solusinya, Anda bisa menjalankan launchctl limitroot lebih awal saat boot, mungkin dari a LaunchDaemon. (...)

Larutan:

Masukkan kode ke /Library/LaunchDaemons/com.apple.launchd.limit.plistoleh bash-script:

#!/bin/bash

echo '<?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>eicar</string>
        <key>ProgramArguments</key>
        <array>
                <string>/bin/launchctl</string>
                <string>limit</string>
                <string>core</string>
                <string>unlimited</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
        <key>ServiceIPC</key>
        <false/>
</dict>
</plist>' | sudo tee /Library/LaunchDaemons/com.apple.launchd.limit.plist
Aax
sumber
1
Bisakah Anda menjelaskan ini lebih banyak? Saya tidak bisa melihat bagaimana 'Memecahkan Masalah' berkaitan dengan masalah awal!
Nick H247
Bukan OP, tapi saya pikir intinya di sini adalah: masukkan plist ini ke dalam /Library/LaunchDaemons, dan bukannya menyuruh launchctlmenjalankan limitperintah, katakan untuk menjalankan setenvperintah dengan PATHdan path path sebagai argumen. launchdharus mengambilnya secara otomatis saat startup dan mendapatkan semacam modifikasi diri segera.
Laird Nelson
5
Xml tidak sepenuhnya disalin. Baris doctype harus dibaca<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
UloPe
6
@ aax bagian mana dari plist yang benar-benar menetapkan variabel lingkungan?
HairOfTheDog
3

Berikut adalah perintah untuk memulihkan perilaku lama:

# create a script that calls launchctl iterating through /etc/launchd.conf
echo '#!/bin/sh

while read line || [[ -n $line ]] ; do launchctl $line ; done < /etc/launchd.conf;
' > /usr/local/bin/launchd.conf.sh

# make it executable
chmod +x /usr/local/bin/launchd.conf.sh

# launch the script at startup
echo '<?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>launchd.conf</string>
  <key>ProgramArguments</key>
  <array>
    <string>sh</string>
    <string>-c</string>
    <string>/usr/local/bin/launchd.conf.sh</string>
  </array>
  <key>RunAtLoad</key>
  <true/>
</dict>
</plist>
' > /Library/LaunchAgents/launchd.conf.plist

Sekarang Anda dapat menentukan perintah seperti setenv JAVA_HOME /Library/Java/Homedi /etc/launchd.conf.

Diperiksa pada El Capitan.

yanchenko
sumber
2

Apa yang berhasil bagi saya (terinspirasi dari terima kasih):

Rekatkan ini ke /Library/LaunchDaemons/com.apple.launchd.limit.plist lalu reboot:

<?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>eicar</string>
  <key>ProgramArguments</key>
  <array>
    <string>/bin/launchctl</string>
    <string>limit</string>
    <string>maxfiles</string>
    <string>16384</string>
    <string>16384</string>
  </array>
  <key>RunAtLoad</key>
  <true/>
  <key>ServiceIPC</key>
  <false/>
</dict>
</plist>

Jika Anda membutuhkannya langkah demi langkah:

  • Luncurkan terminal
  • Ketik sudo su lalu masukkan kata sandi Anda untuk login sebagai root
  • Ketik vi /Library/LaunchDaemons/com.apple.launchd.limit.plist
  • Ketika masuk ke editor vi, tekan tombol i untuk masuk ke mode masukkan lalu rekatkan konten kode yang tepat di atas ( ⌘+v). Ini akan memaksa batas untuk 16384 file per proses dan total 16384 file
  • Simpan file Anda dan berhenti menggunakan escitu:wq
  • Nyalakan ulang sistem Anda, dan periksa apakah berfungsi menggunakan batas perintah launchctl

Saya harap ini membantu Anda.

Baptiste
sumber
10
Apa hubungan solusi ini dengan pengaturan variabel lingkungan?
HairOfTheDog
2

Anda dapat mencoba https://github.com/ersiner/osx-env-sync . Ini menangani baris perintah dan aplikasi GUI dari satu sumber dan bekerja dengan OS X versi terbaru (Yosemite).

Anda dapat menggunakan substitusi path dan trik shell lainnya karena apa yang Anda tulis adalah skrip bash biasa yang bersumber dari bash. Tidak ada batasan .. (Periksa dokumentasi osx-env-sync dan Anda akan memahami bagaimana ini mencapai ini.)

Saya menjawab pertanyaan serupa di sini di mana Anda akan menemukan lebih banyak.

Ersin Er
sumber
-3

Solusinya adalah menambahkan variabel Anda /etc/profile. Maka semuanya berjalan seperti yang diharapkan! Tentu saja Anda HARUS melakukannya sebagai pengguna root dengan sudo nano / etc / profile. Jika Anda mengeditnya dengan cara lain, sistem akan mengeluh dengan profil / etc / yang rusak, bahkan jika Anda mengubah izin untuk melakukan root.

Ilias
sumber
7
Menambahkan variabel lingkungan ke profil sangat rendah karena hanya mempengaruhi proses shell.
UloPe
-5

Saya menambahkan variabel dalam ~ / .bash_profile dengan cara berikut. Setelah Anda selesai restart / logout dan login

export M2_HOME=/Users/robin/softwares/apache-maven-3.2.3
export ANT_HOME=/Users/robin/softwares/apache-ant-1.9.4
launchctl setenv M2_HOME $M2_HOME
launchctl setenv ANT_HOME $ANT_HOME
export PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/Users/robin/softwares/apache-maven-3.2.3/bin:/Users/robin/softwares/apache-ant-1.9.4/bin
launchctl setenv PATH $PATH

CATATAN: tanpa memulai ulang / keluar dan masuk Anda dapat menerapkan perubahan ini menggunakan;

source ~/.bash_profile
Robin
sumber
Perhatikan bahwa Anda tidak perlu keluar dan kembali. Cukup gunakan perintah sumber yaitu sumber .bash_profile.
Michael
2
Juga, masalah dengan metode ini adalah bahwa Anda masih harus membuka terminal sebelum variabel lingkungan tersedia. Lebih baik melakukan apa yang ada di jawaban pertama sehingga tersedia tanpa harus membuka terminal.
Michael
1
Ini tidak berfungsi pada aplikasi yang dimuat melalui SpotLight. stackoverflow.com/questions/135688/…
Rasika Perera
1
Menggunakan file konfigurasi bash adalah bantuan terbatas karena menganggap bahwa Anda selalu mendapat bash sebagai nenek moyang dari proses yang lingkungannya Anda coba untuk efek. Spotlight, finder, emacs, xcode, cronjobs, launchd agent, IDE, browser kontrol sumber, dll. Semua tidak akan memiliki bash sebagai leluhur. Satu-satunya proses yang dapat menjangkau rentang ini secara konsisten adalah launchd.
Ben Hyde