Bagaimana cara membuat layanan unix melihat variabel lingkungan?

52

Saya telah menetapkan variabel lingkungan saya menggunakan /etc/profile:

export VAR=/home/userhome

Lalu jika saya lakukan echo $VARitu menunjukkan/home/userhome

Tetapi ketika saya menaruh referensi ke variabel ini ke dalam /etc/init.d/servicenamefile, itu tidak dapat menemukan variabel ini. Ketika saya menjalankan service servicename statusmenggunakan /etc/init.d/servicenamefile dengan konten berikut:

case "$1" in
status)    
    cd $VAR/dir
    ;;
esac

ia mengatakan /dir: No such file or directory

Tapi itu berfungsi jika saya menjalankan /etc/init.d/servicename statusbukanservice servicename status

Bagaimana saya bisa membuat layanan unix melihat variabel lingkungan?

alternatif
sumber
Perhatikan bahwa menjalankan rcskrip System 5 secara langsung juga tidak beroperasi seperti itu pada sistem operasi systemd, karena semua doa skrip diubah menjadi doa systemctloleh kail tersembunyi.
JdeBP

Jawaban:

70

Masalahnya adalah servicemenghapus semua variabel lingkungan tetapi TERM, PATHdan LANGyang merupakan hal yang baik. Jika Anda mengeksekusi skrip secara langsung, tidak ada yang menghapus variabel lingkungan sehingga semuanya berfungsi.

Anda tidak ingin bergantung pada variabel lingkungan eksternal karena saat startup variabel lingkungan mungkin tidak ada dan sistem init Anda mungkin tidak akan mengaturnya.

Jika Anda masih ingin bergantung pada variabel seperti itu, sumber file dan baca variabel dari itu, misalnya buat /etc/default/servicenamedengan konten:

VAR=value

dan sumber dari skrip init Anda, misalnya:

[ -f /etc/default/service-name ] && . /etc/default/service-name

if [ -z "$VAR" ] ;  then
  echo "VAR is not set, please set it in /etc/default/service-name" >&2
  exit 1
fi

case "$1" in
status)    
    cd "$VAR"/dir
    ;;
esac
Ulrich Dangel
sumber
13
Terima kasih banyak. Untuk pemula Linux lainnya, inilah hal-hal Bash samar. [ ... ]adalah singkatan untuk tes bersyarat; lihat jawaban ini . -fadalah ifargumen untuk memeriksa apakah file ada. &&adalah operator hubung singkat: hanya lakukan perintah kedua jika yang pertama keluar dengan 0. .operator sumber atau titik: baca dan jalankan perintah dari argumen nama file. -zadalah ifargumen untuk memeriksa string yang panjangnya nol. >&2kirim output ke stderr. Lihat juga Pengantar jika .
Mark Berry
@MarkBerry -fadalah bagian dari [, bukan if.
Chris Down
@ ChrisDown, terima kasih. Jadi " [ ... ]adalah singkatan untuk testperintah bersyarat ; lihat jawaban ini . -fAdalah testargumen untuk memeriksa apakah ada file."
Mark Berry
@MarkBerry Benar. Anda dapat menganggap [(atau test) hanya sebagai perintah lain - yang ifdilakukan adalah mengambil tindakan berdasarkan status keluar.
Chris Down
Saya pernah mengalami situasi yang mirip dengan ini, tetapi saya tidak perlu $VARberada dalam skrip init, saya perlu itu tersedia untuk program 2 atau 3 panggilan yang berbeda di bagian hilir skrip init. Misalnya. skrip init memanggil start-stop-daemon yang memanggil Program 1 (Java) yang memanggil Program 2 yang perlu $VAR. Saya mencoba trik dalam jawaban ini tetapi sepertinya tidak berhasil dalam situasi saya. Bagaimana saya bisa memastikan bahwa $VARakan tersedia untuk Program 2?
FrustratedWithFormsDesigner
1

Dalam kasus saya, saya membutuhkan RAILS_ENVyang diatur dalam /etc/bash.bashrc: export RAILS_ENV=staging. Saya menambahkan $(grep RAILS_ENV /etc/bash.bashrc)dan itu membuat variabel tersedia untuk skrip. Saya melakukannya dengan cara ini sehingga saya tidak perlu memasukkan sisa file.

geermc4
sumber
-1

Satu solusi jelek yang juga akan berfungsi:

function exec() {
    args=( $@ )
    command=${args[0]}
    dummy=${args[1]}
    whoami=`whoami`
    if [ -z "$dummy" ]; then
        me=`basename $0`
        runuser -l ${whoami} -c "bash /etc/init.d/${me} ${command} dummy"
    else
       printenv
   fi
}

case $1 in
    status)
        status
        ;;
    start|stop|kill|restart)
        exec $*
        ;;
    *)
        usage
esac
Maksim
sumber