Karakter yang diizinkan dalam nama variabel lingkungan Linux

143

Karakter apa yang diizinkan dalam nama variabel lingkungan Linux? Pencarian sepintas tentang halaman manual dan web hanya menghasilkan informasi tentang cara bekerja dengan variabel, tetapi tidak dengan nama mana yang diizinkan.

Saya memiliki program Java yang memerlukan variabel lingkungan yang ditentukan yang berisi titik, seperti com.example.fancyproperty. Dengan Windows saya dapat mengatur variabel itu, tetapi saya tidak beruntung mengaturnya di linux (dicoba di SuSE dan Ubuntu). Apakah nama variabel itu bahkan diizinkan?

Christian Semrau
sumber
3
Untungnya, saya menemukan bahwa program ini sama senangnya dengan properti sistem Java (dideklarasikan dengan -Dopsi baris perintah), jadi ia bekerja sekarang. Jelas program terlihat di kedua set variabel tanpa memberi tahu saya. Tapi saya masih penasaran tentang nama variabel lingkungan mana yang diperbolehkan.
Christian Semrau
@AlexandrDubinsky saya menghapusnya. Ini mirip tetapi tentang definisi alias tidak persis variabel lingkungan stackoverflow.com/questions/24690640/...
Lime
1
Jika Anda menggunakan Spring , maka SystemEnvironmentPropertySource default juga akan mencari com_example_fancypropertydan COM_EXAMPLE_FANCYPROPERTY.
Aleksandr Dubinsky

Jawaban:

203

Dari Grup Terbuka :

String ini memiliki form name = value; nama tidak boleh mengandung karakter '='. Untuk nilai yang akan portabel di seluruh sistem yang sesuai dengan IEEE Std 1003.1-2001, nilai harus terdiri dari karakter dari set karakter portabel ( kecuali NUL dan seperti yang ditunjukkan di bawah ).

Jadi nama dapat berisi karakter apa pun kecuali = dan NUL, tetapi:

Nama variabel lingkungan yang digunakan oleh utilitas dalam volume Shell dan Utilities dari IEEE Std 1003.1-2001 hanya terdiri dari huruf besar, digit, dan '_' (garis bawah) dari karakter yang ditetapkan dalam Portable Character Set dan tidak dimulai dengan angka . Karakter lain mungkin diizinkan oleh implementasi; aplikasi harus mentolerir keberadaan nama tersebut.

Jadi, meskipun nama-nama itu valid, shell Anda mungkin tidak mendukung apa pun selain huruf, angka, dan garis bawah.

Robert Gamble
sumber
8
Hanya memeriksa: kutipan kedua adalah non-normatif: hanya mengamati bahwa variabel yang didefinisikan POSIX sebagai utilitas khusus adalah [a-zA-Z_][a-zA-Z0-9_]*(secara tersirat menyarankan formulir ini lebih waras), tetapi spesifikasi aktual (kutipan 1) memerlukan semua implementasi untuk mendukung apa pun kecuali =dan NUL?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
3
Juga, "set karakter portabel" pubs.opengroup.org/onlinepubs/000095399/basedefs/… berisi hal-hal seperti spasi dan tidak dapat dicetak: jadi dapatkah kita menggunakan hal-hal itu atau tidak?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
3
Inilah yang saya amati. Shell tidak suka karakter khusus sebagai bagian dari nama variabel. Namun ketika satu program atau skrip (mis. Java atau perl) menginisialisasi variabel dengan karakter khusus dalam namanya dan memanggil executable lain (proses anak), executable yang terakhir dapat mengakses variabel itu tanpa masalah.
oᴉɹǝɥɔ
1
@checksum, UPPERCASE secara eksplisit ditentukan untuk nama variabel dengan arti untuk alat yang ditentukan POSIX, termasuk shell; nama dengan setidaknya satu karakter huruf kecil secara eksplisit disediakan untuk penggunaan aplikasi. Dengan demikian, praktik terbaik sebenarnya adalah memasukkan setidaknya satu karakter huruf kecil ke dalam nama variabel aplikasi Anda untuk memastikan bahwa Anda tidak menimpa secara tidak sengaja (karena menyetel variabel shell akan menimpa variabel lingkungan yang dinamai seperti) variabel yang memiliki arti untuk sistem. Lihat pubs.opengroup.org/onlinepubs/9699919799/basedefs/…
Charles Duffy
2
@CiroSantilli 烏坎 事件 2016 六四 事件 法轮功, Anda dapat menggunakannya dalam variabel lingkungan; Anda tidak dapat menggunakannya dalam variabel shell, dan variabel lingkungan tersebut tidak dijamin dapat diakses dari shell.
Charles Duffy
37

Standar POSIX pada bagian shell dari IEEE Std 1003.1-2008 / IEEE POSIX P1003.2 / ISO 9945.2 Standar Shell dan Tools tidak mendefinisikan konvensi leksikal untuk nama variabel, namun pandangan sekilas pada sumber mengungkapkan bahwa ia menggunakan sesuatu yang mirip dengan

[a-zA-Z_]+[a-zA-Z0-9_]*

(Edit: Menambahkan garis bawah yang hilang di kelas karakter ke-2.)

Catatan singkat, karena beberapa shell tidak mendukung tanda + di regex, kemungkinan regex yang lebih portabel adalah:

[a-zA-Z_]{1,}[a-zA-Z0-9_]{0,}

Aiden Bell
sumber
4
Terima kasih, Aiden. Saya pikir ada garis bawah yang hilang pada set kedua kurung siku: Mungkin harus membaca: [a-zA-Z_][a-zA-Z0-9_]* Bagi mereka seperti saya yang menemukan referensi ke bash-4.1 sedikit kabur (616'000 baris kode), berikut adalah beberapa petunjuk untuk temukan baris kode yang relevan: subst.c: param_expand(), in the default case-> general.h:/ * Tentukan dengan tepat apa yang dimaksud dengan pengidentifikasi shell hukum. * / #define legal_variable_starter (c) (ISALPHA (c) || ​​(c == ' ')) #define legal_variable_char (c) (ISALNUM (c) || ​​c == ' ')
Chris
3
Anda tidak perlu plus itu di kelas karakter pertama.
scravy
2
@scravy benar, meskipun saya mengambil regexp dari sumbernya jadi saya akan tetap menggunakan +.
Aiden Bell
4
POSIX mendefinisikan: Nama 3.231 a word consisting solely of underscores, digits, and alphabetics from the portable character set. The first character of a name is not a digit .
Tidak di bagian shell, tetapi benar-benar ada standar POSIX yang mencakup konvensi untuk penamaan variabel lingkungan (dan benar-benar membahas nama-nama yang dicadangkan untuk penggunaan shell). Lihat pubs.opengroup.org/onlinepubs/9699919799/basedefs/…
Charles Duffy
12

Pengujian cepat saya menunjukkan bahwa mereka pada dasarnya mengikuti aturan yang sama seperti nama variabel C, yaitu

  1. az, AZ, _dan 0-9
  2. Mungkin TIDAK dimulai dengan angka

Jadi ini tidak termasuk .di dalamnya. Setiap nama variabel ilegal dikreditkan dengan unknown command.

Ini diuji dalam ZSH, yang sebagian besar kompatibel dengan BASH.

LukeN
sumber
6

Tergantung pada apa yang Anda maksud dengan 'diizinkan'.

Mengabaikan Windows untuk saat ini:

Lingkungan adalah array string, diteruskan ke fungsi utama suatu program. Jika Anda membaca exec (2), Anda tidak akan melihat persyaratan atau batasan pada string ini selain dari null-termination.

Secara konvensi, setiap string terdiri dari NAME = nilai. Tidak ada konvensi kutipan, jadi Anda tidak dapat memiliki '=' pada nama di konvensi ini.

Manusia normal mengatur string ini dengan mendiskusikannya dengan cangkangnya. Setiap shell memiliki ide sendiri tentang apa yang merupakan NAMA variabel yang valid, jadi Anda harus membaca halaman manual untuk shell-of-the-moment untuk melihat apa yang dipikirkannya.

Secara umum, hal-hal seperti com.baseball.spit = fleagh adalah properti sistem Java, dan apakah beberapa program Java bersedia untuk kembali ke lingkungan, lebih baik untuk menentukannya dengan -D.

bmargulies
sumber
Saya seharusnya sudah sampai pada kesimpulan bahwa variabel diformat seperti properti sistem Java, daripada mencoba untuk mengaturnya sebagai variabel lingkungan.
Christian Semrau
5

Itu tergantung pada shell. Saya menduga Anda menggunakan bash secara default, dalam hal ini huruf, angka, dan garis bawah dibolehkan, tetapi Anda tidak dapat memulai nama variabel dengan angka. Pada Bash v.3, periode tidak diperbolehkan dalam nama variabel .

ire_and_curses
sumber
4

YA KAMU BISA MELAKUKANNYA.

Gunakan execdan envperintah untuk mengimplementasikan adegan ini.

Tes Jadwal di Docker

docker run -it --rm alpine:3.10

Jalankan perintah dalam wadah:

exec env spring.application_name=happy-variable-name ${SHELL:-/bin/sh}

Verifikasi variabel lingkungan:

HOSTNAME=bd0bccfdc53b
SHLVL=2
HOME=/root
spring.application_name=happy-variable-name
TERM=xterm
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/

Gunakan ps auxuntuk memverifikasi PID tidak berubah

PID   USER     TIME  COMMAND
    1 root      0:00 /bin/sh
   12 root      0:00 ps aux

Gunakan pythonuntuk memverifikasi variabel environmentem

apk add python
python -c 'import os; print(os.environ["spring.application_name"])'

OUTPUT adalah happy-variable-name.

Apa yang terjadi?

  1. Shell call builtin exec
  2. Shell builtin exec memanggil syscall.exec membuat proses 'env' untuk mengganti shell saat ini
  3. proses env panggilan syscall.execvp buat proses '/ bin / sh' untuk menggantikan proses env

Cara lain

  • Gambar buruh pelabuhan

Jika Anda menggunakan buruh pelabuhan, Anda dapat mengatur variabel di Dockerfile

FROM busybox
ENV xx.f%^&*()$#ff=1234
  • Kubernetes configmap

Jika Anda menggunakan kubernetes, Anda dapat mengatur variabel dengan ConfigMap

test.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: foo-config
data:
  "xx.ff-bar": "1234"

---
apiVersion: v1
kind: Pod
metadata:
  name: foobar
spec:
  containers:
    - name: test-container
      image: k8s.gcr.io/busybox
      command: [ "/bin/sh", "-c", "env" ]
      envFrom:
      - configMapRef:
          name: foo-config
  restartPolicy: Never

Sebarkan pod kubectl apply -f test.yaml

Verifikasi kubectl logs foobarhasil:

xx.ff-bar=1234

ConfigMap mengizinkan '-', '_' atau '.'

Zelika
sumber
0

Meskipun sebagian besar shell tidak akan mengizinkan pengaturan variabel lingkungan (seperti yang disebutkan dalam jawaban lain), jika Anda membutuhkannya, Anda dapat menjalankan program lain dengan menggunakan variabel lingkungan yang tidak standar env(1).

Misalnya, menghapus semua lingkungan dan pengaturan Strange.Env:Varke nilai foo, dan menjalankan program perl yang mencetaknya:

env -i Strange.Env:Var=foo perl -MData::Dumper -E 'say Dumper(\%ENV)'

akan dicetak

$VAR1 = {
          'Strange.Env:Var' => 'foo'
        };
Matija Nalis
sumber