Apa cara distro / shell-agnostik terbaik untuk mengatur variabel lingkungan?

31

Pertanyaannya mengatakan itu semua. Saat ini saya menggunakan Arch Linux dan zsh, tetapi saya ingin solusi yang (minimal) berfungsi baik pada VT dan xterms dan juga (mudah-mudahan, lebih disukai) akan terus bekerja jika saya beralih distro atau shell.

Saya telah mendengar jawaban yang sangat berbeda untuk pertanyaan ini di dokumen distro yang berbeda. Ubuntu mengatakan "gunakan .pam_environment". Saya pikir di Arch apa yang mereka rekomendasikan tergantung pada shell Anda. Saat ini saya meletakkan semuanya di. Profil dan jika shell tidak sumber itu untuk beberapa alasan (misalnya bash jika. Bash_profile ada), saya menimpanya dengan secara manual sumber itu. Tapi sepertinya harus ada cara yang lebih baik.

strugee
sumber
2
Ini tidak ada hubungannya dengan distro dan semuanya ada hubungannya dengan shell. Tidak yakin ada cara portabel untuk melakukannya.
Joseph R.
Hmm. Luar biasa .
strugee

Jawaban:

29

Sayangnya tidak ada lokasi sepenuhnya portabel untuk mengatur variabel lingkungan. Dua file yang paling dekat adalah ~/.profile, yang merupakan lokasi tradisional dan bekerja di luar kotak pada banyak pengaturan, dan ~/.pam_environment, modern, biasa tapi alternatif yang terbatas.

Apa yang dimasukkan ~/.pam_environment

File ~/.pam_environmentdibaca oleh semua metode login yang menggunakan PAM dan yang memiliki file ini diaktifkan. Ini mencakup sebagian besar sistem Linux saat ini.

Keuntungan utama ~/.pam_environmentadalah bahwa (ketika diaktifkan) itu dibaca sebelum shell pengguna dimulai, jadi itu berfungsi terlepas dari jenis sesi, shell login dan kompleksitas lainnya. Ia bahkan berfungsi untuk login non-interaktif seperti su -c somecommanddan ssh somecommand.

Keterbatasan utama ~/.pam_environmentadalah bahwa Anda hanya dapat menempatkan tugas sederhana di sana, bukan sintaks shell kompleks. Sintaks dari file ini adalah sebagai berikut.

  • File diurai baris demi baris.
  • Ruang putih terkemuka diabaikan.
  • Anda dapat secara opsional memulai garis dengan exportdan satu ruang (bukan tab, gambar saja).
  • Setelah itu, setiap baris harus memiliki bentuk di VAR=VALUEmana VAR terdiri dari huruf, angka, dan garis bawah.
  • # memulai komentar, tidak dapat muncul dalam nilai.
  • Jika VALUE dimulai dengan 'atau "dan berisi kutipan identik lainnya, maka VAR diatur ke string di antara kutipan (semuanya setelah kutipan kedua diabaikan). Kalau tidak, VAR diatur ke string setelah =tanda.
  • Jika tidak ada =, variabel dihapus dari lingkungan.

Jadi, terbalik, ~/.pam_environmentbekerja dalam berbagai keadaan. Pada sisi negatifnya, Anda tidak dapat memiliki pengaturan dinamis seperti mendasarkan nilai variabel pada variabel lain (misalnya menambahkan direktori ke PATH) atau menggunakan output dari perintah (mis. Tes apakah direktori atau program ada), dan beberapa karakter ( #'", baris baru) tidak mungkin atau sulit untuk dimasukkan ke dalam nilai.

Apa yang dimasukkan ~/.profile

File ini harus memiliki sintaks sh portabel (POSIX). Hanya gunakan ekstensi ksh atau bash (array [[ … ]],, dll.) Jika Anda tahu bahwa sistem Anda memiliki shell ini sebagai /bin/sh.

File ini dapat dibaca oleh skrip dalam aplikasi otomatis, jadi tidak boleh memanggil program yang menghasilkan output atau panggilan apa pun exec. Jika Anda ingin melakukan itu pada login mode teks, lakukan hanya untuk shell interaktif. Contoh:

case $- in *i*)
  # Display a message if I have new mail
  if mail -e; then echo 'You have new mail'; fi
  # If zsh is available, and this looks like a text-mode login, run zsh
  case "`ps $PPID` " in
    *" login "*)
      if type zsh >/dev/null 2>/dev/null; then exec zsh; fi;;
  esac
esac

Ini adalah contoh penggunaan /bin/shsebagai shell login Anda dan beralih ke shell favorit Anda. Lihat juga bagaimana saya bisa menggunakan bash sebagai shell login saya ketika sysadmin saya menolak untuk membiarkan saya mengubahnya

Kapan ~/.profiletidak membaca login non-grafis?

Shell login yang berbeda membaca file yang berbeda.

Jika shell login Anda adalah bash

Bash membaca ~/.bash_loginatau ~/.bash_profilejika ada, bukan ~/.profile. Juga bash tidak membaca ~/.bashrcdi shell login bahkan jika itu interaktif. Agar tidak perlu lagi mengingat quirks ini, buat a ~/.bash_profiledengan dua baris berikut:

. ~/.profile
case $- in *i*) . ~/.bashrc;; esac

Lihat juga File pengaturan mana yang harus digunakan untuk mengatur variabel lingkungan dengan bash?

Jika shell login Anda adalah zsh

Zsh membaca ~/.zprofiledan ~/.zlogin, tetapi tidak ~/.profile. Zsh memiliki sintaks yang berbeda dari sh, tetapi dapat membaca ~/.profiledalam mode emulasi sh. Anda dapat menggunakan ini untuk ~/.zprofile:

emulate sh -c '. ~/.profile'

Lihat juga Zsh tidak memukul ~ /. Profil

Jika shell login Anda adalah beberapa shell lain

Tidak banyak yang dapat Anda lakukan di sana, singkat untuk digunakan /bin/shsebagai shell login Anda dan shell favorit Anda (seperti ikan) sebagai shell interaktif saja. Itu yang saya lakukan dengan zsh. Lihat di atas untuk contoh meminta shell lain dari ~/.profile.

Perintah jarak jauh

Saat menjalankan perintah jarak jauh tanpa melalui shell interaktif, tidak semua shell membaca file startup.

Ksh membaca file yang ditentukan oleh ENVvariabel, jika Anda berhasil meneruskannya.

Bash membaca ~/.bashrcjika tidak interaktif (!) Dan proses induknya disebut rshdatau sshd. Jadi Anda bisa mulai ~/.bashrcdengan

if [[ $- != *i* ]]; then
  . ~/.profile
  return
fi

Zsh selalu membaca ~/.zshenvsaat dimulai. Gunakan dengan hati-hati, karena ini dibaca oleh setiap instance zsh, bahkan ketika itu adalah subshell tempat Anda mengatur variabel lain. Jika zsh adalah shell login Anda dan Anda ingin menggunakannya untuk mengatur variabel hanya untuk perintah jarak jauh, gunakan pelindung: setel beberapa variabel ~/.profile, seperti MY_ENVIRONMENT_HAS_BEEN_SET=yes, dan periksa penjaga ini sebelum membaca ~/.profile.

if [[ -z $MY_ENVIRONMENT_HAS_BEEN_SET ]]; then emulate sh -c '~/.profile'; fi

Kasus login grafis

Banyak distribusi, manajer tampilan, dan lingkungan desktop yang diatur untuk dijalankan ~/.profile, baik dengan mengambilnya secara eksplisit dari skrip startup atau dengan menjalankan shell login.

Sayangnya, tidak ada metode umum untuk menangani kombinasi distro / DM / DE di mana ~/.profiletidak dibaca.

Jika Anda menggunakan sesi tradisional yang dimulai oleh ~/.xsession, ini adalah tempat di mana Anda harus mengatur variabel lingkungan Anda; lakukan dengan sumber ~/.profile(yaitu . ~/.profile). Perhatikan bahwa dalam beberapa pengaturan, skrip startup lingkungan desktop akan sumber ~/.profilelagi.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
apa yang case $- in *i*)harus dilakukan
qodeninja
2
@qodeninja Melaksanakan instruksi berikut (hingga pencocokan ;;atau esac) jika $-cocok dengan polanya *i*, yaitu jika $-berisi i, yaitu jika shell bersifat interaktif.
Gilles 'SO- stop being evil'
$-adalah serangkaian opsi shell yang saat ini ditetapkan. (seperti set -x). iberarti shell interaktif.
Peter Cordes
Tidak bisakah Anda hanya sumber file umum, katakanlah ~/.config/env, bahkan tanpa persaingan?
Kevin Suttle
1
@ StéphaneChazelas Itu pandangan yang murni. Saya menjaga .profilekepatuhan saya dengan cangkang Bourne yang cukup tua, tetapi saya menyadari bahwa beberapa orang tidak peduli. Saya tidak membenci orang dengan anggapan bahwa sh = bash untuk file mereka sendiri, saya hanya peduli jika mereka menerbitkan #!/bin/shskrip yang menggunakan fitur bash.
Gilles 'SANGAT berhenti menjadi jahat'
4

Sejauh yang saya tahu tidak ada distro dan shell standar agnostik bagaimana mengatur variabel lingkungan.

Standar yang paling umum dan de facto tampaknya /etc/profiledan ~/.profile. Tampaknya yang paling umum kedua adalah /etc/environmentdan ~/.pam_environment.

Tampak bagi saya bahwa semua dokumentasi yang saya temukan juga sudah Anda temukan. Saya mendaftarkan mereka di sini untuk pembaca lain.

  • Debian merekomendasikan /etc/profiledan ~/.profile( tautan ).
  • Ubuntu merekomendasikan /etc/environmentdan ~/.pam_environment( tautan ).
  • Arch Linux menyebutkan, antara lain, /etc/profiledan /etc/environment( tautan ).

Bonus: teks yang mempertanyakan penggunaan dan / atau penyalahgunaan /etc/environmentdalam bahasa debian ( tautan , pembaruan terakhir 2008).

lesmana
sumber
Terlepas dari file yang Anda gunakan, Anda masih akan menemukan sintaks yang tidak kompatibel antara shell yang berbeda.
Joseph R.
1
@ JosephephR. sebagian besar shell tidak memiliki kompatibilitas sh? Selama Anda tetap berpegang pada POSIX, saya akan berpikir Anda akan baik-baik saja ...
evilsoup
1
AFAIK Anda tidak dapat menetapkan variabel dalam cshdan berteman dengan cara POSIX (Anda perlu sesuatu seperti setatau setenv)
Joseph R.
0

Saya menambahkan skrip berikut ~ / bin / agnostic_setenv:

#!/bin/csh -f
set args = ($*)
if ($#args == 1) then
   echo "export $args[1]="
   exit 0
endif

if ($#args == 2) then
   if ("$args[1]" =~ *csh*) then 
      echo "setenv $args[2]"
      exit 0
   else
      echo "export $args[1]=$args[2]"
      exit 0
   endif
endif

echo "setenv $args[2] $args[3]"

Dan di ~ / .perl-homedir saya menggunakan:

eval `${HOME}/bin/agnostic_setenv $shell PERL_HOMEDIR 0`

Skrip serupa untuk agnostic_unsetenv:

#!/bin/csh -f
set args = ($*)
if ($#args == 1) then
   echo "export $args[1]"
   exit 0
endif

echo "unsetenv $args[2]"
exit 0
Kobi
sumber