Di mana saya harus mengekspor variabel lingkungan sehingga semua kombinasi bash / dash, interaktif / non-interaktif, login / non-login, akan mengambilnya?


11

Inilah motivasi untuk pertanyaan itu:

Saya menggunakan Ubuntu 12,04 LTS 2 dengan desktop Unity. Dalam file .bashrc saya, saya menambahkan beberapa direktori ke variabel PATH saya dan mendefinisikan beberapa variabel lingkungan, seperti JAVA_HOME. Ketika saya meluncurkan aplikasi dari terminal (menjalankan bash, shell default saya), ini berfungsi dengan baik, tetapi untuk beberapa pintasan yang menggunakan peluncur Unity, mereka menjalankan aplikasi yang tampaknya ditentukan untuk menggunakan #! / Bin / sh, yang alias / bin / dash, dan mereka tidak mengambil konten ~ / .bashrc atau ~ / .profile.

Saya kira saya bisa mengubah semua cara pintas ini untuk menggunakan / bin / bash alih-alih / bin / sh untuk memaksanya mengambil perubahan .bashrc, tapi itu tampaknya sangat gila.

Mengingat bahwa Ubuntu 12.04 (secara default) alias / bin / sh ke / bin / dash dan bahwa shell default saya adalah / bin / bash, apakah ada satu tempat di mana saya dapat memilih untuk memodifikasi PATH dan mendefinisikan variabel lingkungan jika saya menginginkannya untuk hadir dalam semua keadaan ini:

  1. Setiap kali saya membuat shell pesta non-login (menggunakan terminal dalam kesatuan)
  2. Setiap kali saya membuat shell pesta login (misalnya, login jarak jauh dari ssh)
  3. Setiap kali saya menggunakan peluncur aplikasi Unity (mengingat bahwa peluncur menggunakan / bin / sh).
  4. Setiap kali tugas cron dijalankan (mengingat bahwa SHELL = / bin / sh in / etc / crontab).

Jika saya mengerti dengan benar, saya menduga bahwa:

  • (1) / (2) dan (3) / (4) berbeda karena (1) / (2) adalah bash dan (3) / (4) adalah tanda hubung.
  • (1) dan (2) berbeda karena file yang bash pilih untuk memuat berbeda tergantung pada apakah itu shell login atau tidak.
  • (3) dan (4) berbeda karena (3) akan datang di beberapa titik setelah saya masuk (dan karenanya ~ /. Profil akan dipasok oleh salah satu proses induknya, sementara (4) akan datang di beberapa titik ketika saya tidak masuk, dan karenanya ~ /. profil tidak akan dibaca.

(Saya tidak akan terkejut jika faktor-faktor lain juga penting, seperti apakah shell itu interaktif atau tidak, jadi mungkin ada lebih banyak kombinasi yang bahkan belum saya antisipasi ... Saya senang pertanyaan saya "membaik " dalam hal itu.)

Saya berharap bahwa pada titik tertentu, seseorang pasti telah membuat semacam panduan yang memberi tahu Anda bagaimana / di mana memodifikasi variabel lingkungan dengan cara shell-independent (atau setidaknya cara yang kompatibel dengan dash / bash) ... Saya hanya bisa ' Tampaknya tidak menemukan istilah penelusuran yang tepat untuk menemukan panduan semacam itu.

Solusi atau petunjuk untuk solusi sangat dihargai!

Diperbarui:

  • Klarifikasi: Ini adalah pengguna Ubuntu default yang dibuat oleh proses instalasi 12.04, jadi tidak ada yang mewah. Itu memang memiliki ~ / .profile (yang secara eksplisit sumber ~ / .bashrc), dan satu-satunya file ~ / .bash * yang ada adalah .bashrc, .bash_history, dan .bash_logout ... jadi tidak ada .bash_profile.
  • Penekanan pada ruang lingkup: Saya tidak terlalu peduli dengan cangkang selain cangkang interaktif bawaan (bash) dan skrip apa pun yang menggunakan / bin / sh (alias terputus-putus), jadi tidak perlu menyulitkan ini dengan tambahan apa pun untuk tcsh / ksh / zsh / dll. dukung.

2
Tempatkan dalam satu file kemudian biarkan file rc lainnya sumber itu.
konsolebox

Menurut halaman manual dasbor yang saya miliki di sini seharusnya membaca $ HOME / .profile untuk shell login.
Etan Reisner

@konsolebox File rc mana? AFAICT, tanda hubung tidak memiliki file rc. Dan seperti yang saya nyatakan, tanda hubung sepertinya tidak mengambil isi ~ /. Profil.

@EtanReisner Ya, dan ini adalah pertanyaannya. Ketika dasbor tidak berjalan sebagai shell login (dan karenanya ~ / .profile tidak bersumber), lalu bagaimana?

@Mickalot Apakah Anda menjalankan tanda hubung secara interaktif? Jika tidak coba tambahkan opsi -l padanya.
konsolebox

Jawaban:


9

Doa shell adalah hal yang rumit. Halaman manual bash and dash memiliki INVOCATIONbagian tentang ini.

Singkatnya kata mereka (ada lebih detail di halaman manual, Anda harus membacanya):

When bash is                   | it reads
-------------------------------|----------
login shell                    | /etc/profile and then the first of ~/.bash_profile, ~/.bash_login or ~/.profile that exists.
                               |
interactive non-login shell    | /etc/bash.bashrc then ~/.bashrc
                               |
non-interactive shell          | The contents of $BASH_ENV (if it exists)
                               |
interactive (as "sh")          | The contents of $ENV (if it exists)

-

When dash is                   | it reads
-------------------------------|---------
login shell                    | /etc/profile then .profile
                               |
interactive shell              | The contents of ENV (it it exists, can be set in .profile as well as in initial environment)

Saya tidak tahu tentang kerang lain begitu saja karena saya tidak pernah menggunakan salah satu dari mereka. Taruhan terbaik Anda mungkin untuk menetapkan beberapa variabel lingkungan untuk menunjuk pada skrip lokasi umum dan secara manual sumber itu (jika perlu) dalam beberapa kasus yang tidak tercakup.


Sayangnya, inti dari masalah ini adalah yang hilang dari tabel dasbor Anda. Ketika desktop Unity mengaktifkan skrip apa pun yang dimulai dengan #! / Bin / sh, itu meluncurkan (apa yang saya asumsikan) sebuah shell dash non-login, non-interaktif. Jadi pertanyaannya adalah: bagaimana cara membuat variabel lingkungan yang sama tersedia di sana yang ada di tempat lain dalam matriks?

Baik. Saya membayangkan itu sebabnya bash menambahkan BASH_ENV untuk slot itu. Mengingat bahwa dasbor tampaknya tidak memiliki apa pun yang berfungsi di slot itu, saya tidak yakin Anda dapat menyelesaikan masalah itu tanpa memengaruhi perubahan lingkungan aplikasi yang meluncurkan dasbor (sedemikian rupa sehingga dasbor mewarisinya). Ini akan membutuhkan variabel lingkungan yang diatur di lingkungan X Anda yang merupakan tempat .xsession (rc) komentar dari @Mickalot berperan. Ini masih menyisakan, seperti yang ditunjukkannya, item empat ditinggalkan (tapi saya percaya itu sebenarnya agak disengaja).
Etan Reisner

Karena saya menggunakan Ubuntu 12.04 LTS, cron sebenarnya adalah pixie-cron, jadi saya dapat mendefinisikan variabel env dalam file crontab saya ... Saya menduga SHELL = / bin / bash dan BASH_ENV = ~ / .bashrc harus melakukannya?

3

Jadi, ada beberapa cara untuk mendekati ini. Banyak orang akan:

Sebuah. Memiliki satu file yang memiliki kesamaan dengan semua shell sh-style Anda, katakan .shcommondan di masing-masing .profile .bashrc .kshrcet cetra, cukup sumber ini dengan. .shcommon

b. Masukkan semuanya ke dalam .profiledan sumber ini dari file lain.

Hal-hal yang diperlukan untuk shell tertentu atau untuk shell interaktif vs non-interaktif kemudian dapat masuk ke file yang sesuai sebelum sumber .shcommon

Secara pribadi, saya tidak suka mengatur banyak file. Jadi, saya menggunakan pendekatan berikut:

Pertama, semua yang saya butuhkan masuk .profile Karena saya memiliki beberapa hal spesifik bash dan ksh, saya menentukan nama shell saat ini menggunakan yang berikut:

# get name of current shell
# strip leading - from login shell
export SHELLNAME="${0#-}"

dan kemudian memiliki perintah untuk shell tertentu dalam sesuatu seperti berikut (beberapa akan lebih suka pernyataan kasus).

if [ "$SHELLNAME" = 'bash' ]
then
    shopt -s checkwinsize

elif [ "$SHELLNAME" = 'ksh' ]
then
    stty erase ^?
fi

Jika saya memiliki perintah yang hanya dapat dijalankan di shell interaktif, saya menggunakan yang berikut ini:

# check for interactive flag i in shell options $-
# in bash and ksh you could use the following, but breaks in dash
# if [[ $- == *i* ]]
if [ "$(echo $- | grep i)" != "" ]
then
  fortune
fi

Hal-hal yang umum di semua kerang gaya sh, misalnya, PATHbisa saja pergi di atas.

Lalu, saya menggunakan symlink untuk memuat file yang sama ini di semua shell sh-style:

ln -s .profile .bashrc
ln -s .profile .kshrc

Beberapa catatan tambahan, jika Anda memiliki .bash_profile, maka bash akan memuat ini alih-alih .profiletetapi tanda hubung dan ksh akan tetap memuat .profile Ini mungkin menjadi bagian dari masalah Anda.

Juga, Anda mungkin ingin mempertimbangkan untuk menggunakan #!/bin/bashskrip Anda alih-alih #!/bin/dashkecuali Anda benar-benar menginginkan skrip yang kompatibel dengan POSIX. bash memiliki banyak fitur tambahan yang sangat bagus dan dash atau bash dipanggil karena ia akan menonaktifkan banyak fitur ini.

Juga, halaman bash man melakukan pekerjaan dengan baik untuk menjelaskan kapan .profileversus .bashrcdimuat. Aturan serupa berlaku untuk ksh. dash memuat .profilesaat login dan memungkinkan Anda untuk memuat file pada startup shell interaktif yang ditentukan menggunakan ENVvariabel lingkungan di .profile(periksa halaman manual dasbor juga dan cari .profile).


Bisakah Anda tidak hanya menguji $ 0 untuk nama shell? Apakah ada cangkang / kasing yang tidak berfungsi?
Etan Reisner

Demikian pula, apakah memeriksa i dalam $ - tidak cukup untuk tes shell interaktif? (Ini akan memicu pada shell interaktif tanpa tty saya berikan tapi itu mungkin atau mungkin bukan efek samping yang tidak diinginkan.)
Etan Reisner

@Etan: Hrm, saya tahu bahwa saya pertama kali mencoba $0dan mengalami masalah ... Sepertinya saya tidak ingat persis apa yang mereka pikirkan. Masuk langsung ke konsol memang ditampilkan $0sebagai -bashganti bashtapi itu bisa diperbaiki.

@Etan: Ya, memeriksa saya $-juga akan berfungsi. Saya harus memikirkan kapan Anda akan memiliki shell interaktif tanpa tty? Solusi Anda memang memiliki "rasa" yang lebih baik karena beberapa alasan, saya dapat mengubahnya.

The -di -bashberarti "shell login" tapi ya Anda akan perlu untuk akun untuk itu di tempat di mana Anda menguji nilai atau ingin menampilkannya kepada seseorang.
Etan Reisner

0

Karena kasus (1) dan (2) diselesaikan dengan sumber variabel lingkungan saya di .bashrc dan .profile, pertanyaan sebenarnya adalah "apa nama file tempat saya sumber variabel yang sama untuk (3) dan (4).

Sepertinya ada jawaban untuk bagian (3) dari pertanyaan (bagaimana cara mendapatkan variabel lingkungan untuk diimpor di desktop Unity) di askubuntu . Saran yang ada adalah membuat file ~ / .xsessionrc yang akan dipasok oleh / etc / X11 / Xsession. (Saya sudah mencoba ini, dan sepertinya berhasil ... yay!)

Saya masih bingung dengan apa yang harus dilakukan untuk (4). Tentunya, jika saya membuat cron job (atau daemon), saya dapat mengganti '/ bin / foo' dengan sesuatu seperti 'bash -i -c / bin / foo' untuk memaksanya menggunakan bash untuk memuat variabel lingkungan yang tepat, tetapi ini juga berarti bahwa saya harus mengotak-atik alat pihak ketiga yang mungkin menginstal tugas daemon atau tugas cron atas nama saya. Yuk.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.