Các ký tự được phép trong tên biến môi trường Linux


143

Những ký tự nào được phép trong tên biến môi trường Linux? Tìm kiếm đáng chú ý của tôi về các trang man và web chỉ tạo ra thông tin về cách làm việc với các biến, nhưng không cho phép tên nào được phép.

Tôi có một chương trình Java yêu cầu một biến môi trường được xác định có chứa một dấu chấm, như thế com.example.fancyproperty. Với Windows tôi có thể đặt biến đó, nhưng tôi không gặp may khi cài đặt nó trong linux (đã thử trong SuSE và Ubuntu). Là tên biến thậm chí được phép?


3
May mắn thay, tôi thấy rằng chương trình này rất hài lòng với thuộc tính hệ thống Java (được khai báo với -Dtùy chọn dòng lệnh), vì vậy nó hoạt động ngay bây giờ. Rõ ràng chương trình nhìn vào cả hai bộ biến mà không cho tôi biết. Nhưng tôi vẫn tò mò về tên biến môi trường nào được phép.
Christian Semrau

@AleksandrDubinsky Tôi đã xóa nó. Điều này tương tự nhưng về định nghĩa bí danh không chính xác là các biến môi trường stackoverflow.com/questions/24690640/ Khăn
Lime

1
Nếu bạn đang sử dụng Spring , thì SystemEn MôiPropertySource mặc định cũng sẽ tìm kiếm com_example_fancypropertyCOM_EXAMPLE_FANCYPROPERTY.
Alexanderr Dubinsky

Câu trả lời:


203

Từ nhóm mở :

Các chuỗi này có dạng tên = value; Tên không được chứa ký tự '='. Để các giá trị có thể di động trên các hệ thống tuân thủ theo tiêu chuẩn IEEE Std 1003.1-2001, giá trị sẽ bao gồm các ký tự từ bộ ký tự di động ( trừ NUL và như được chỉ ra bên dưới ).

Vì vậy, tên có thể chứa bất kỳ ký tự nào ngoại trừ = và NUL, nhưng:

Tên biến môi trường được sử dụng bởi các tiện ích trong khối Shell và Tiện ích của IEEE Std 1003.1-2001 chỉ bao gồm các chữ cái in hoa, chữ số và '_' (gạch dưới) từ các ký tự được xác định trong Bộ ký tự di động và không bắt đầu bằng một chữ số . Các nhân vật khác có thể được cho phép bởi một thực hiện; các ứng dụng phải chịu đựng sự hiện diện của các tên đó.

Vì vậy, trong khi tên có thể hợp lệ, trình bao của bạn có thể không hỗ trợ bất cứ điều gì ngoài các chữ cái, số và dấu gạch dưới.


8
Chỉ cần kiểm tra: trích dẫn thứ hai là không quy tắc: nó chỉ quan sát rằng các biến mà POSIX định nghĩa là đặc biệt cho các tiện ích của nó là [a-zA-Z_][a-zA-Z0-9_]*(ngầm định đề xuất biểu mẫu này là saner), nhưng thông số thực tế (trích dẫn 1) yêu cầu tất cả thực hiện để hỗ trợ bất cứ điều gì ngoài =NUL?
Ciro Santilli 郝海东 冠状 病 事件

3
Ngoài ra, "bộ ký tự di động" pubs.opengroup.org/onlinepub/000095399/basingefs/ gợi chứa những thứ như khoảng trắng và không in được: vậy chúng ta có thể sử dụng những thứ đó hay không?
Ciro Santilli 郝海东 冠状 病 事件

3
Đây chính xác là những gì tôi quan sát. Shell không thích các ký tự đặc biệt như là một phần của tên biến. Tuy nhiên, khi một chương trình hoặc tập lệnh (ví dụ java hoặc perl) khởi tạo một biến có các ký tự đặc biệt trong tên của nó và gọi một tệp thực thi khác (một tiến trình con) thì tệp thực thi sau có thể truy cập vào biến đó mà không gặp vấn đề gì.
oᴉɹǝɥɔ

1
@checksum, UPPERCASE được chỉ định rõ ràng cho các tên biến có ý nghĩa với các công cụ được chỉ định POSIX, bao gồm cả shell; tên có ít nhất một ký tự chữ thường được dành riêng cho sử dụng ứng dụng. Do đó, cách tốt nhất là thực sự bao gồm ít nhất một ký tự chữ thường trong tên biến của ứng dụng của bạn để đảm bảo rằng bạn không vô tình ghi đè (vì việc đặt biến shell sẽ ghi đè lên bất kỳ biến môi trường giống như tên nào) hệ thống. Xem pubs.opengroup.org/onlinepub/9699919799/basingefs/iêu
Charles Duffy

2
@CiroSantilli 2016 六四 事件, bạn có thể sử dụng chúng trong các biến môi trường; bạn không thể sử dụng chúng trong các biến shell và các biến môi trường đó không được đảm bảo có thể truy cập được từ shell.
Charles Duffy

37

Các tiêu chuẩn POSIX trên phần vỏ của IEEE Std 1003.1-2008 / IEEE POSIX P1003.2 / ISO 9945.2 Tiêu chuẩn Shell và Công cụ không xác định quy ước từ vựng cho các tên biến, tuy nhiên, một cái nhìn cursory về nguồn cho thấy nó sử dụng một cái gì đó tương tự

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

(Chỉnh sửa: Đã thêm dấu gạch dưới bị thiếu trong lớp ký tự thứ 2.)

Một lưu ý nhanh, vì một số shell không hỗ trợ + trong regex, một regex có khả năng di động cao hơn có thể là:

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


4
Cảm ơn, Aiden. Tôi nghĩ rằng có một dấu gạch dưới bị thiếu trong bộ dấu ngoặc vuông thứ hai: Có lẽ nên đọc: [a-zA-Z_][a-zA-Z0-9_]* Đối với những người như tôi tìm thấy tham chiếu đến bash-4.1 một chút mơ hồ (616'000 dòng mã), đây là một vài gợi ý để tìm các dòng mã có liên quan: subst.c: param_expand(), in the default case-> general.h:/ * Xác định chính xác những gì một định danh shell hợp pháp bao gồm. * / #define Legal_variable_starter (c) (ISALPHA (c) || ​​(c == ' ')) #define Legal_variable_char (c) (ISALNUM (c) || ​​c == ' ')
Chris

3
Bạn không cần điều đó cộng với trong lớp nhân vật đầu tiên.
cào bằng

2
@scravy đúng, mặc dù tôi đã lấy regrec từ nguồn nên tôi sẽ giữ dấu +.
Aiden Bell

4
POSIX định nghĩa: Tên 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 .

Không nằm trong phần shell, nhưng hoàn toàn có các tiêu chuẩn POSIX bao gồm các quy ước cho việc đặt tên biến môi trường (và thực sự thảo luận về các tên được dành riêng cho việc sử dụng shell). Xem pubs.opengroup.org/onlinepub/9699919799/basingefs/iêu
Charles Duffy

12

Thử nghiệm nhanh của tôi cho thấy về cơ bản chúng tuân theo các quy tắc giống như tên biến C có, cụ thể là

  1. az, AZ _và 0-9
  2. Có thể KHÔNG bắt đầu bằng một số

Vì vậy, điều này loại trừ .bên trong chúng. Bất kỳ tên biến bất hợp pháp được ghi có unknown command.

Điều này đã được thử nghiệm trong ZSH, phần lớn tương thích với BASH.


6

Phụ thuộc vào những gì bạn có nghĩa là 'được phép'.

Bỏ qua Windows cho nonce:

Môi trường là một chuỗi các chuỗi, được truyền cho chức năng chính của chương trình. Nếu bạn đọc execve (2), bạn sẽ thấy không có yêu cầu hoặc giới hạn nào đối với các chuỗi này ngoài việc kết thúc null.

Theo quy ước, mỗi chuỗi bao gồm NAME = value. Không có quy ước trích dẫn, vì vậy bạn không thể có '=' trong tên trong quy ước này.

Người bình thường thiết lập các chuỗi này bằng cách thảo luận về chúng với vỏ của chúng. Mỗi shell có ý tưởng riêng về TÊN biến hợp lệ là gì, vì vậy bạn phải đọc trang hướng dẫn để biết thời điểm đó để xem nó nghĩ gì.

Nói chung, những thứ như com.baseball.spit = fleagh là các thuộc tính của hệ thống Java và liệu một số chương trình Java có sẵn sàng quay trở lại môi trường hay không, tốt hơn là chỉ định chúng với -D.


Tôi nên sớm đi đến kết luận rằng biến được định dạng giống như một thuộc tính hệ thống Java, thay vì cố gắng đặt nó làm biến môi trường.
Christian Semrau


4

CÓ, BẠN CÓ THỂ LÀM ĐIỀU ĐÓ.

Sử dụng execenvlệnh để thực hiện cảnh này.

Kiểm tra lịch thi đấu trong Docker

docker run -it --rm alpine:3.10

Chạy lệnh trong container:

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

Xác minh các biến môi trường:

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

Sử dụng ps auxđể xác minh PID không thay đổi

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

Sử dụng pythonđể xác minh biến môi trường

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

ĐẦU RA là happy-variable-name.

Chuyện gì xảy ra

  1. Shell thực hiện cuộc gọi dựng sẵn
  2. Shell dựng sẵn thực hiện cuộc gọi syscall.exec tạo quá trình 'env' để thay thế shell hiện tại
  3. env process gọi syscall.execvp tạo tiến trình '/ bin / sh' để thay thế tiến trình env

Cách khác

  • Docker hình ảnh

Nếu bạn đang sử dụng docker, bạn có thể đặt biến trong Dockerfile

FROM busybox
ENV xx.f%^&*()$#ff=1234
  • Cấu hình Kubernetes

Nếu bạn đang sử dụng kubernetes, bạn có thể đặt biến bằng ConfigMap

kiểm tra.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

Triển khai pod kubectl apply -f test.yaml

Xác minh kubectl logs foobarđầu ra:

xx.ff-bar=1234

Cấu hình cho phép '-', '_' hoặc '.'


0

Mặc dù hầu hết shell sẽ không cho phép thiết lập các biến môi trường (như đã đề cập trong các câu trả lời khác), nếu bạn có nhu cầu, bạn có thể thực hiện các chương trình khác với các biến môi trường không chuẩn bằng cách sử dụng env(1).

Ví dụ: xóa tất cả môi trường và cài đặt Strange.Env:Varthành giá trị foovà thực hiện chương trình perl in nó:

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

sẽ in

$VAR1 = {
          'Strange.Env:Var' => 'foo'
        };
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.