Đặt biến môi trường qua launchd.conf không còn hoạt động trong OS X Yosemite / El Capitan / macOS Sierra / Mojave?


189

Có vẻ như launchd.confkhông tải biến môi trường của tôi nữa. Đã có người khác nhận thấy điều đó không?

Có một giải pháp khác để thiết lập các biến môi trường vĩnh viễn?


Nó hoạt động và làm cho nó có sẵn trong ứng dụng nhưng không có trong thiết bị đầu cuối
Chang Zhao

Câu trả lời:


158

Tạo một environment.plisttệp ~/Library/LaunchAgents/với nội dung này:

<?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>

Bạn có thể thêm nhiều launchctllệnh bên trong <string></string>khối.

Các plistsẽ kích hoạt sau khi hệ thống khởi động lại. Bạn cũng có thể sử dụng launchctl load ~/Library/LaunchAgents/environment.plistđể khởi chạy nó ngay lập tức.

[Biên tập]

Giải pháp tương tự cũng hoạt động ở El Capitan.

Xcode 7.0+ không đánh giá các biến môi trường theo mặc định. Hành vi cũ có thể được kích hoạt bằng lệnh này:

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

[Biên tập]

Có một vài tình huống trong đó điều này không thực sự hiệu quả. Nếu máy tính được khởi động lại và "Mở lại cửa sổ khi đăng nhập lại", cửa sổ mở lại có thể không thấy các biến (Có lẽ chúng được mở trước khi tác nhân được chạy). Ngoài ra, nếu bạn đăng nhập qua ssh, các biến sẽ không được đặt (vì vậy bạn sẽ cần đặt chúng trong ~ / .bash_profile). Cuối cùng, điều này dường như không hoạt động cho PATH trên El Capitan và Sierra. Điều đó cần được đặt thông qua 'launchctl config đường dẫn người dùng ...' và trong / etc / path.


20
Không cần phải khởi động lại! Bạn có thể thực hiện "launchctl start môi
trường.plist

1
Điều này sẽ không hoạt động với biến PATH cho tôi. Vì vậy, ngoài cách tiếp cận này để đặt các biến khác, tôi đặt biến PATH trong ~ / .bash_profile của tôi. Điều này có thể không hoạt động cho mọi trường hợp nhưng cho đến nay tôi không có vấn đề gì.
djule5

6
Hình ra: Để làm việc mà không cần khởi động lại, nó phải là "launchctl load môi trường.plist ", không bắt đầu
Dave Hartnoll 16/2/2015

2
À, vâng. Không có gì giống như cài đặt cấu hình tối nghĩa xuất hiện chính xác 9 lần trên toàn bộ internet (google UseSanitizedBuildSystemEnvironment).
Ohad Schneider

2
Hoạt động trên Sierra cũng vậy
Shwouchk

64

[ Câu trả lời gốc ]: Bạn vẫn có thể sử dụnglaunchctl setenv variablename value để đặt biến sao cho tất cả các ứng dụng được chọn (các ứng dụng đồ họa được khởi động qua Dock hoặc Spotlight, ngoài các biến được bắt đầu qua thiết bị đầu cuối).

Rõ ràng là bạn sẽ không muốn làm điều này mỗi khi bạn đăng nhập.

[ Chỉnh sửa ]: Để tránh điều này, hãy khởi chạy AppleScript Editor, nhập một lệnh như thế này:

do shell script "launchctl setenv variablename value"

(Sử dụng nhiều dòng nếu bạn muốn đặt nhiều biến)

Bây giờ lưu ( + s) dưới định dạng Tệp: Ứng dụng . Cuối cùng mở System SettingsNgười dùng & NhómMục đăng nhập và thêm ứng dụng mới của bạn.

[ Câu trả lời gốc ]: Để xử lý xung quanh vị trí này, tất cả các biến bạn muốn xác định trong tập lệnh shell ngắn, sau đó hãy xem câu trả lời trước đó về cách chạy tập lệnh khi đăng nhập MacOS . Bằng cách đó, tập lệnh sẽ được gọi khi người dùng đăng nhập.

[ Chỉnh sửa ]: Không có giải pháp nào là hoàn hảo vì các biến sẽ chỉ được đặt cho cụ thể đó người dùng nhưng tôi hy vọng / đoán đó có thể là tất cả những gì bạn yêu cầu.

Nếu bạn có nhiều người dùng, bạn có thể đặt Mục đăng nhập theo cách thủ công cho từng người trong số họ hoặc đặt một bản sao com.user.loginscript.plist trong mỗi Thư viện / LaunchAgents cục bộ của họ , chỉ vào cùng một tập lệnh shell.

Cấp, cả hai cách giải quyết này đều không thuận tiện như /etc/launchd.conf .

[ Chỉnh sửa thêm ]: Một người dùng bên dưới đề cập rằng điều này không hiệu quả với anh ta. Tuy nhiên tôi đã thử nghiệm trên nhiều máy Yosemite và nó hoạt động với tôi. Nếu bạn gặp sự cố, hãy nhớ rằng bạn sẽ cần khởi động lại các ứng dụng để việc này có hiệu lực. Ngoài ra, nếu bạn đặt biến trong thiết bị đầu cuối thông qua ~ / .profile hoặc ~ / .bash_profile , chúng sẽ ghi đè lên những thứ được đặt thông qua launchctl setenv cho các ứng dụng được khởi động từ trình bao .


5
Theo như tôi có thể nói, một nhược điểm của kỹ thuật này là (các) biến sẽ không được đặt cho bất kỳ ứng dụng nào khác bắt đầu khi đăng nhập. Vì vậy, ví dụ nếu bạn mở Terminal, biến sẽ được đặt, nhưng nếu bạn đăng xuất và bật lại, khi Terminal tự động khởi động lại, biến sẽ không được đặt ...
JasonD

Tôi đã thử giải pháp này và nó cũng không hiệu quả với tôi. Nhưng tôi đặc biệt mong đợi Java IDE (IntelliJ) của tôi sẽ nhận các sửa đổi đường dẫn của tôi và nó thì không. Tất cả mọi thứ hoạt động tốt từ thiết bị đầu cuối. Nó có thể là một lỗi trong IntelliJ. Vẫn bực bội khi Apple loại bỏ chức năng này. Tôi đã gọi cho Apple và họ không hữu ích lắm.
Jason

Điều này đang làm việc cho tôi, nhưng bạn có biết phải làm gì để thêm các biến môi trường vào sudo không?
etiennenoel

2
Điều này sẽ hoạt động nói chung, tuy nhiên có một lỗi trong Yosemite (ít nhất là 10.10.0 và 10.10.1) khi cài đặt $ PATH không hoạt động theo cách này. Apple nhận thức được lỗi này. Hiện tại (kể từ ngày 10.10.1), không có cách nào để thiết lập $ PATH trên toàn hệ thống cho các ứng dụng GUI.
TJ Luoma

3
Sau khi bạn sử dụng một trong các phương pháp được đề cập ở trên và khởi động lại máy tính xách tay của mình - Đảm bảo bạn mở lại rõ ràng các ứng dụng (như iTerm, terminal, Eclipse, IDEA hoặc bất cứ thứ gì bạn đang sử dụng). Nếu bạn không khởi động lại chúng một cách rõ ràng và nếu trong khi khởi động lại OSx, hộp kiểm được chọn để "Khởi động lại cửa sổ khi đăng nhập lại" (đó là mặc định) - những chương trình đó sẽ không đọc các biến môi trường mới.
Ran

21

Có thể đặt biến môi trường trên Mac OS X 10.10 Yosemite với 3 tệp + 2 lệnh.

Tệp chính với định nghĩa biến môi trường:

$ 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"

Định nghĩa dịch vụ để tải các biến môi trường cho các ứng dụng người dùng (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>

Định nghĩa dịch vụ tương tự cho các ứng dụng người dùng 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>

Và cuối cùng chúng ta nên đăng ký các dịch vụ này:

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

Những gì chúng ta nhận được:

  1. Nơi duy nhất để khai báo các biến môi trường hệ thống: / etc / môi trường
  2. Tự động cập nhật tức thời các biến môi trường sau khi sửa đổi tệp / etc / môi trường - chỉ cần khởi chạy lại ứng dụng của bạn

Vấn đề / vấn đề:

Để các biến env của bạn được các ứng dụng lấy chính xác sau khi khởi động lại hệ thống bạn sẽ cần:

  • hoặc đăng nhập hai lần: đăng nhập => đăng xuất => đăng nhập
  • hoặc đóng và mở lại các ứng dụng theo cách thủ công, trong đó các biến env nên được thực hiện
  • hoặc KHÔNG sử dụng tính năng "Mở lại cửa sổ khi đăng nhập lại".

Điều này xảy ra do Apple từ chối đặt hàng rõ ràng các dịch vụ được tải, vì vậy các biến env được đăng ký song song với việc xử lý "hàng đợi mở lại".

Nhưng thực tế, tôi khởi động lại hệ thống của mình chỉ vài lần mỗi năm (trên các bản cập nhật lớn), vì vậy nó không phải là vấn đề lớn.


Ý tưởng tuyệt vời. Tôi đã thử nó và nó hoạt động cho hầu hết các biến môi trường (như JAVA_HOME), nhưng không phải cho PATHbiến (xem câu hỏi của tôi khi hỏi khác nhau ).
halloleo

4
PATH nên được đặt với tập tin / etc / path. Chỉ cần thêm đường dẫn tùy chỉnh của bạn vào cuối tập tin này.
ursa

Tôi không quen thuộc lắm launchd, nhưng không thể tải các Daemon đó khi khởi động (tức là trước khi đăng nhập)? Điều đó sẽ phá vỡ tất cả các vấn đề bạn đề cập.
Egon

Tôi thích cách tiếp cận ở trên nhưng có một vấn đề kỳ lạ để quản lý. Sau khi khởi động lại, một gen VARNAME trả về cho tôi giá trị đúng nhưng echo $ VARNAME không trả về gì. Điều gì có thể là một lý do cho điều này? Tôi đã đăng nó lên stackoverflow.com/questions/27045137/ và cũng hy vọng rằng bất cứ ai ở đây cũng có ý tưởng
ctp

Đảm bảo rằng các quyền của tệp / etc / môi trường được mô tả ở trên.
imanuelcostigan

6

Trích dẫn từ

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

Sau nhiều lần cân nhắc, kỹ thuật đã loại bỏ tính năng này. Các tập tin /etc/launchd.confđã được cố ý loại bỏ vì lý do bảo mật. Như một giải pháp thay thế, bạn có thể chạy launchctl limitroot sớm trong khi khởi động, có lẽ từ a LaunchDaemon. (...)

Giải pháp:

Đặt mã vào /Library/LaunchDaemons/com.apple.launchd.limit.plistbằng 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

1
Bạn có thể giải thích điều này nhiều hơn một chút? Tôi không thể thấy 'Giải quyết vấn đề' liên quan đến vấn đề ban đầu như thế nào!
Nick H247

Không phải OP, nhưng tôi nghĩ ý chính ở đây là: đặt cái này vào /Library/LaunchDaemonsvà thay vì bảo launchctlchạy limitlệnh, hãy bảo nó chạy setenvlệnh với PATHvà một chuỗi đường dẫn làm đối số. launchdnên tự động lấy nó khi khởi động và nhận loại tự sửa đổi gần như ngay lập tức.
Laird Nelson

5
Xml được sao chép không đầy đủ. Dòng doctype nên đọc<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
UloPe

6
@aax phần nào của plist đó thực sự đặt một biến môi trường?
HairOfTheDog

3

Dưới đây là các lệnh để khôi phục hành vi cũ:

# 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

Bây giờ bạn có thể chỉ định các lệnh như setenv JAVA_HOME /Library/Java/Home trong /etc/launchd.conf.

Đã kiểm tra trên El Capitan.


2

Điều gì đã làm việc cho tôi (lấy cảm hứng từ aax 'cảm ơn):

Dán cái này vào / L Library / LaDDaemons / com.apple.launchd.limit.plist sau đó khởi động lại:

<?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>

Nếu bạn cần nó từng bước:

  • Ra mắt thiết bị đầu cuối
  • Loại sudo su sau đó nhập mật khẩu để đăng nhập như là người chủ
  • Kiểu vi /Library/LaunchDaemons/com.apple.launchd.limit.plist
  • Khi vào trình soạn thảo vi, nhấn phím i để vào chế độ chèn, sau đó dán nội dung mã chính xác ở trên (⌘+v ). Điều này sẽ buộc giới hạn ở 16384 tệp trên mỗi quy trình và tổng số 16384 tệp
  • Lưu tệp của bạn và thoát bằng cách sử dụng escsau đó:wq
  • Khởi động lại hệ thống của bạn và kiểm tra xem nó có hoạt động không bằng cách sử dụng giới hạn lệnh launchctl

Tôi hy vọng điều này đã giúp bạn.


10
Giải pháp này có liên quan gì đến việc thiết lập các biến môi trường?
HairOfTheDog

2

Bạn có thể thử https://github.com/ersiner/osx-env-sync . Nó xử lý cả hai dòng lệnh và ứng dụng GUI từ một nguồn duy nhất và hoạt động cùng với phiên bản OS X mới nhất (Yosemite) mới nhất.

Bạn có thể sử dụng thay thế đường dẫn và các thủ thuật shell khác vì những gì bạn viết là tập lệnh bash thông thường sẽ có nguồn gốc từ bash ở vị trí đầu tiên. Không có giới hạn .. (Kiểm tra tài liệu đồng bộ hóa osx-env và bạn sẽ hiểu làm thế nào nó đạt được điều này.)

Tôi đã trả lời một câu hỏi tương tự ở đây nơi bạn sẽ tìm thấy nhiều hơn.


-3

Giải pháp là thêm biến của bạn vào /etc/profile. Sau đó, mọi thứ hoạt động như mong đợi! Tất nhiên bạn PHẢI làm điều đó như một người dùng root với sudo nano / etc / profile. Nếu bạn chỉnh sửa nó bằng bất kỳ cách nào khác, hệ thống sẽ khiếu nại với cấu hình / etc / profile bị hỏng, ngay cả khi bạn thay đổi quyền thành root.


7
Thêm các biến môi trường vào hồ sơ rất kém vì nó chỉ ảnh hưởng đến các quy trình shell.
UloPe

-5

Tôi đã thêm các biến trong ~ / .bash_profile theo cách sau. Sau khi bạn hoàn thành khởi động lại / đăng xuất và đăng nhập

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

LƯU Ý: không cần khởi động lại / đăng xuất và đăng nhập, bạn có thể áp dụng những thay đổi này bằng cách sử dụng;

source ~/.bash_profile

Lưu ý rằng bạn không phải đăng xuất và đăng nhập lại. Chỉ cần sử dụng lệnh nguồn tức là nguồn .bash_profile.
Michael

2
Ngoài ra, vấn đề với phương pháp này là bạn vẫn phải mở một thiết bị đầu cuối trước khi các biến môi trường có sẵn. Tốt hơn là làm những gì trong câu trả lời đầu tiên để chúng có sẵn mà không cần phải mở một thiết bị đầu cuối.
Michael

1
Điều này không hoạt động trên các ứng dụng được tải thông qua SpotLight. stackoverflow.com/questions/135688/
trộm

1
Sử dụng các tệp cấu hình bash sẽ giúp ích rất nhiều vì nó cho rằng bạn luôn có bash như một tổ tiên của quá trình mà môi trường bạn đang cố gắng thực hiện. Spotlight, công cụ tìm, emacs, xcode, cronjobs, launchd agent, bất kỳ IDE, trình duyệt kiểm soát nguồn, v.v., tất cả sẽ không có bash như tổ tiên. Quá trình duy nhất có thể kéo dài những điều này một cách nhất quán là launchd.
Ben Hyde
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.