อักขระที่อนุญาตในชื่อตัวแปรสภาพแวดล้อม Linux


143

อนุญาตให้ใช้อักขระใดบ้างในชื่อตัวแปรสภาพแวดล้อม Linux การค้นหาคร่าวๆของหน้า man และเว็บของฉันสร้างเฉพาะข้อมูลเกี่ยวกับวิธีการทำงานกับตัวแปร แต่ไม่อนุญาตให้ใช้ชื่อใด

ฉันมีโปรแกรม Java com.example.fancypropertyที่จะต้องมีการกำหนดตัวแปรสภาพแวดล้อมที่มีจุดเช่น ด้วย Windows ฉันสามารถตั้งค่าตัวแปรนั้นได้ แต่ฉันไม่มีโชคในการตั้งค่าใน linux (ทดลองใช้ใน SuSE และ Ubuntu) ชื่อตัวแปรนั้นได้รับอนุญาตหรือไม่


3
โชคดีที่ฉันพบว่าโปรแกรมนี้มีความสุขกับคุณสมบัติของระบบ Java (ประกาศด้วย-Dตัวเลือกบรรทัดคำสั่ง) ดังนั้นจึงสามารถใช้งานได้ในขณะนี้ เห็นได้ชัดว่าโปรแกรมดูในชุดตัวแปรทั้งสองโดยไม่บอกฉัน แต่ฉันก็ยังสงสัยว่าอนุญาตให้ใช้ชื่อตัวแปรสภาพแวดล้อมใดได้บ้าง
Christian Semrau

@AleksandrDubinsky ฉันลบมัน นี้คล้ายกัน แต่เกี่ยวกับคำจำกัดความของนามแฝงไม่ใช่ตัวแปรสภาพแวดล้อมอย่างแน่นอนstackoverflow.com/questions/24690640/…
Lime

1
หากคุณกำลังใช้ฤดูใบไม้ผลิแล้ว SystemEnvironmentPropertySource เริ่มต้นยังจะมองขึ้นไปและcom_example_fancyproperty COM_EXAMPLE_FANCYPROPERTY
Aleksandr Dubinsky

คำตอบ:


203

จากกลุ่มเปิด :

สตริงเหล่านี้มีรูปแบบชื่อ = ค่า; ชื่อจะต้องไม่มีตัวอักษร '=' สำหรับค่าที่จะพกพาข้ามระบบที่สอดคล้องกับ IEEE Std 1003.1-2001 ค่าจะต้องประกอบด้วยอักขระจากชุดอักขระแบบพกพา ( ยกเว้น NUL และตามที่ระบุไว้ด้านล่าง )

ดังนั้นชื่ออาจมีอักขระใด ๆ ยกเว้น = และ NUL แต่:

ชื่อตัวแปรสภาพแวดล้อมที่ใช้โดยยูทิลิตี้ในปริมาณเชลล์และยูทิลิตี้ของ IEEE Std 1003.1-2001 ประกอบด้วยเฉพาะตัวอักษรตัวพิมพ์ใหญ่ตัวเลขและ '_' (ขีดล่าง)จากอักขระที่กำหนดในชุดอักขระแบบพกพาและไม่ขึ้นต้นด้วยตัวเลข . ตัวละครอื่น ๆ อาจได้รับอนุญาตจากการนำไปใช้; แอปพลิเคชันจะต้องทนต่อการปรากฏตัวของชื่อดังกล่าว

ดังนั้นในขณะที่ชื่ออาจใช้ได้เชลล์ของคุณอาจไม่สนับสนุนสิ่งใดนอกจากตัวอักษรตัวเลขและขีดล่าง


8
เพียงแค่ตรวจสอบ: อัญประกาศที่สองนั้นไม่ใช่กฎเกณฑ์: เพียงแค่สังเกตว่าตัวแปรที่ POSIX กำหนดว่าพิเศษสำหรับยูทิลิตี้ของมันคือ[a-zA-Z_][a-zA-Z0-9_]*(โดยนัยแนะนำรูปแบบนี้คือ saner) แต่สเป็คที่แท้จริง (ราคา 1) ต้องการการใช้งานทั้งหมด=และNUL?
Ciro Santilli 郝海东冠状病六四事件法轮功

3
นอกจากนี้ "ชุดอักขระแบบพกพา" pubs.opengroup.org/onlinepubs/000095399/basedefs/ ......มีสิ่งต่าง ๆ เช่นช่องว่างและที่ไม่สามารถพิมพ์ได้: เราสามารถใช้สิ่งเหล่านั้นได้หรือไม่?
Ciro Santilli 郝海东冠状病六四事件法轮功

3
นี่คือสิ่งที่ฉันสังเกต เชลล์ไม่ชอบอักขระพิเศษเป็นส่วนหนึ่งของชื่อตัวแปร อย่างไรก็ตามเมื่อหนึ่งโปรแกรมหรือสคริปต์ (เช่น java หรือ perl) เริ่มต้นตัวแปรที่มีอักขระพิเศษในชื่อของมันและเรียกใช้ปฏิบัติการอื่น (กระบวนการลูก) ปฏิบัติการที่หลังสามารถเข้าถึงตัวแปรนั้นได้โดยไม่มีปัญหา
oᴉɹǝɥɔ

1
@checksum, UPPERCASE ถูกระบุไว้อย่างชัดเจนสำหรับชื่อตัวแปรที่มีความหมายกับเครื่องมือที่ระบุโดย POSIX รวมถึงเชลล์ ชื่อที่มีอักขระตัวพิมพ์เล็กอย่างน้อยหนึ่งตัวจะถูกสงวนไว้อย่างชัดเจนสำหรับการใช้งานแอปพลิเคชัน ดังนั้นแนวปฏิบัติที่ดีที่สุดคือการรวมอักขระตัวพิมพ์เล็กอย่างน้อยหนึ่งตัวในชื่อตัวแปรของแอปพลิเคชันของคุณเพื่อให้แน่ใจว่าคุณไม่ได้เขียนทับโดยไม่ตั้งใจ (การตั้งค่าตัวแปรเชลล์จะเขียนทับตัวแปรสภาพแวดล้อมที่มีชื่อเหมือนกัน) ระบบ. ดูpubs.opengroup.org/onlinepubs/9699919799/basedefs/…
Charles Duffy

2
@CiroSantilli 烏坎事件 2016 六四事件法轮功คุณสามารถใช้พวกเขาในตัวแปรสภาพแวดล้อม คุณไม่สามารถใช้มันในตัวแปรเชลล์และตัวแปรสภาพแวดล้อมเหล่านั้นไม่รับประกันว่าจะสามารถเข้าถึงได้จากเชลล์
ชาร์ลส์ดัฟฟี่

37

มาตรฐาน POSIX ในส่วนเปลือกของ IEEE Std 1,003.1-2,008 / IEEE POSIX P1003.2 / ISO 9945.2 เชลล์และเครื่องมือมาตรฐานไม่ได้กำหนดประชุมศัพท์สำหรับชื่อตัวแปร แต่คร่าวๆ ดูที่แหล่งที่มาแสดงให้เห็นว่าจะใช้สิ่งที่คล้ายกับ

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

(แก้ไข: เพิ่มขีดเส้นใต้ที่ขาดหายไปในคลาสอักขระที่ 2)

บันทึกย่ออย่างรวดเร็วเนื่องจากเชลล์บางตัวไม่สนับสนุนเครื่องหมาย + ใน regex อาจเป็น regex แบบพกพาที่อาจมีมากขึ้น:

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


4
ขอบคุณไอเดน ฉันคิดว่ามีขีดเส้นใต้ที่ขาดหายไปในชุดที่สองของเหลี่ยม: มันน่าจะอ่านได้: [a-zA-Z_][a-zA-Z0-9_]* สำหรับคนอย่างฉันที่ค้นหาการอ้างอิงถึง bash-4.1 เล็กน้อยคลุมเครือ (616'000 บรรทัดของโค้ด) นี่คือคำแนะนำเล็กน้อยสำหรับ ค้นหาบรรทัดของรหัสที่เกี่ยวข้อง: subst.c: param_expand(), in the default case-> general.h:/ * กำหนดว่าตัวระบุเชลล์ทางกฎหมายประกอบด้วยอะไร * / #define legal_variable_starter (c) (ISALPHA (c) || ​​(c == ' ')) #define legal_variable_char (c) (ISALNUM (c) || ​​c == ' ')
คริส

3
คุณไม่จำเป็นต้องมีเครื่องหมายบวกในคลาสอักขระตัวแรก
scravy

2
@ scravy จริง แต่ฉันเอา regexp จากแหล่งที่มาดังนั้นฉันจะเก็บไว้ +
Aiden Bell

4
POSIX กำหนด: 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ชื่อ

ไม่ได้อยู่ในส่วนของเชลล์ แต่มีมาตรฐาน POSIX ที่รวมถึงข้อกำหนดสำหรับการตั้งชื่อตัวแปรสภาพแวดล้อม (และพูดถึงชื่อที่สงวนไว้สำหรับการใช้งานเชลล์จริง ๆ ) ดูpubs.opengroup.org/onlinepubs/9699919799/basedefs/…
Charles Duffy

12

การทดสอบอย่างรวดเร็วของฉันแสดงให้เห็นว่าพวกเขาโดยทั่วไปปฏิบัติตามกฎเดียวกันกับชื่อตัวแปร C คือ:

  1. az, AZ _และ 0-9
  2. อาจไม่เริ่มต้นด้วยตัวเลข

ดังนั้นสิ่งนี้จึงไม่รวม.อยู่ในพวกเขา ชื่อตัวแปรใด ๆ unknown commandที่ผิดกฎหมายจะให้เครดิตกับ

สิ่งนี้ได้รับการทดสอบใน ZSH ซึ่งส่วนใหญ่เข้ากันได้กับ BASH


6

ขึ้นอยู่กับสิ่งที่คุณหมายถึงโดย 'อนุญาต'

ละเว้น Windows สำหรับ nonce:

สภาพแวดล้อมคืออาร์เรย์ของสตริงที่ส่งผ่านไปยังฟังก์ชันหลักของโปรแกรม หากคุณอ่าน execve (2) คุณจะไม่เห็นข้อกำหนดหรือข้อ จำกัด เกี่ยวกับสตริงเหล่านี้ที่นอกเหนือจากการยกเลิกแบบ null

ตามแบบแผนแต่ละสตริงประกอบด้วย NAME = value ไม่มีแบบแผนการอ้างดังนั้นคุณไม่สามารถมี '=' ในชื่อในแบบแผนนี้

มนุษย์ปกติตั้งค่าสตริงเหล่านี้โดยคุยกับพวกมันด้วยเปลือก แต่ละเชลล์มีแนวคิดของชื่อตัวแปรที่ถูกต้องดังนั้นคุณต้องอ่าน man page สำหรับ shell-of-the-moment เพื่อดูว่ามันคิดอะไร

โดยทั่วไปสิ่งต่าง ๆ เช่น com.baseball.spit = fleagh เป็นคุณสมบัติของระบบ Java และไม่ว่าโปรแกรม Java บางโปรแกรมยินดีที่จะถอยกลับไปสู่สภาพแวดล้อมหรือไม่ก็ควรระบุด้วย -D


ฉันควรได้ข้อสรุปก่อนหน้านี้ว่าตัวแปรถูกจัดรูปแบบเช่นคุณสมบัติระบบ Java แทนที่จะพยายามตั้งเป็นตัวแปรสภาพแวดล้อม
Christian Semrau

5

มันขึ้นอยู่กับเปลือก ฉันคาดเดาว่าคุณกำลังใช้ bash โดยค่าเริ่มต้นซึ่งในกรณีนี้จะอนุญาตให้ใช้ตัวอักษรตัวเลขและขีดล่าง แต่คุณไม่สามารถเริ่มต้นชื่อตัวแปรด้วยตัวเลขได้ ในฐานะของทุบตี v.3, ช่วงเวลาที่ไม่ได้รับอนุญาตภายในชื่อตัวแปร


4

ใช่คุณสามารถทำได้

ใช้execและenvคำสั่งเพื่อใช้ฉากนี้

ทดสอบการติดตั้งใน Docker

docker run -it --rm alpine:3.10

เรียกใช้คำสั่งในคอนเทนเนอร์:

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

ตรวจสอบตัวแปรสภาพแวดล้อม:

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=/

ใช้ps auxเพื่อตรวจสอบ PID ไม่เปลี่ยนแปลง

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

ใช้pythonเพื่อตรวจสอบตัวแปรสภาพแวดล้อม

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

happy-variable-nameเอาท์พุท

เกิดอะไรขึ้น?

  1. การเรียก Shell ในตัว exec
  2. Shell builtin exec เรียก syscall.exec สร้างกระบวนการ 'env' เพื่อแทนที่เชลล์ปัจจุบัน
  3. การเรียกกระบวนการ env syscall.execvp สร้างกระบวนการ '/ bin / sh' เพื่อแทนที่กระบวนการ env

อีกวิธีหนึ่ง

  • ภาพนักเทียบท่า

หากคุณใช้นักเทียบท่าคุณสามารถตั้งค่าตัวแปรใน Dockerfile

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

หากคุณกำลังใช้ kubernetes คุณสามารถตั้งค่าตัวแปรโดย 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

ปรับใช้พ็อด kubectl apply -f test.yaml

ตรวจสอบkubectl logs foobarผลลัพธ์:

xx.ff-bar=1234

ConfigMap อนุญาตให้ '-', '_' หรือ '.'


0

แม้ว่าเชลล์ส่วนใหญ่จะไม่อนุญาตให้ตั้งค่าตัวแปรสภาพแวดล้อม (ดังที่กล่าวไว้ในคำตอบอื่น ๆ ) หากคุณต้องการคุณสามารถรันโปรแกรมอื่น ๆ โดยใช้ตัวแปรสภาพแวดล้อมที่ไม่เป็นมาตรฐานenv(1)ได้

ตัวอย่างเช่นการลบสภาพแวดล้อมและการตั้งStrange.Env:Varค่าfooทั้งหมดและดำเนินการโปรแกรม perl ที่พิมพ์:

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

จะพิมพ์

$VAR1 = {
          'Strange.Env:Var' => 'foo'
        };
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.