$$ có nghĩa là gì trong vỏ?


143

Tôi đã từng đọc một cách để có được một tên tệp duy nhất trong một vỏ cho các tệp tạm thời là sử dụng ký hiệu đô la kép ( $$). Điều này không tạo ra một số thay đổi theo thời gian ... nhưng nếu bạn gọi nó liên tục, nó sẽ trả về cùng một số. (Giải pháp là chỉ sử dụng thời gian.)

Tôi tò mò muốn biết $$thực sự là gì và tại sao nó lại được đề xuất như một cách để tạo ra tên tệp độc đáo.

Câu trả lời:


102

Trong Bash $$là ID tiến trình, như đã lưu ý trong các bình luận, không an toàn khi sử dụng làm tên tệp tạm thời vì nhiều lý do.

Đối với tên tệp tạm thời, sử dụng mktemplệnh.


35
Đối với những người chỉ nhìn vào câu trả lời hàng đầu, $$ thậm chí không ổn đối với một tệp duy nhất nếu viết vào thư mục có thể ghi công khai (ví dụ: / tmp). Thật dễ dàng để xả rác / tmp với các liên kết tượng trưng sẽ khiến tập lệnh của bạn viết ở đâu đó không mong muốn. mktemp tốt hơn nhiều.
Chris Jester-Young

4
Vâng, sử dụng $$ sẽ gây ra một lỗ hổng bảo mật khó chịu. Đừng làm điều đó.
emk

7
Hoặc người hỏi câu hỏi nên đặt câu trả lời được xếp hạng cao hơn bên dưới làm câu trả lời được chấp nhận ...
jtimberman

6
Tôi thêm "đô la" cho SEO.
Antoine

1
Nếu $$ chỉ xuất ra pid, làm sao nó "không an toàn"? Lỗ hổng bảo mật được tạo ra do thiết kế kém không sử dụng PID trong tên tệp tmp ... Nếu bạn quan tâm đến tính toàn vẹn của đầu ra đi đến tmp rất nhiều, có lẽ bạn thậm chí không nên đặt nó ở vị trí đầu tiên? $$ sẽ không gây ra lỗ hổng bảo mật, thiếu tầm nhìn xa
niken

113

$$là ID tiến trình (PID) trong bash. Sử dụng $$là một ý tưởng tồi, bởi vì nó thường sẽ tạo ra một điều kiện chủng tộc và cho phép kịch bản shell của bạn bị kẻ tấn công lật đổ. Xem, ví dụ, tất cả những người đã tạo các tệp tạm thời không an toàn và phải đưa ra các lời khuyên bảo mật.

Thay vào đó, sử dụng mktemp. Các trang man Linux cho mktemp là tuyệt vời. Đây là một số mã ví dụ từ nó:

tempfoo=`basename $0`
TMPFILE=`mktemp -t ${tempfoo}` || exit 1
echo "program output" >> $TMPFILE

3
Cảm ơn. Các mktemptùy chọn -thiện đang bị phản đối (tôi nghĩ vì những vấn đề với các char -). Sử dụng mktemp ${tempfoo}.XXXXXXnhững ngày này . Tôi có quyền tự do để cập nhật bài viết của bạn.
Sebastian

1
Cũng xin lưu ý rằng backtick không được dùng nữa , vì vậy hãy sử dụng TMPFILE=$(mktemp)thay thế.
Michael Kopp


7

Mỗi quá trình trong một hệ điều hành giống như UNIX đều có một định danh duy nhất (tạm thời) là PID. Không có hai tiến trình nào chạy cùng một lúc có thể có cùng một PID và $$ đề cập đến PID của đối tượng bash đang chạy tập lệnh.

Đây không phải là một trình xác thực duy nhất theo nghĩa là nó sẽ không bao giờ được sử dụng lại (thực sự, các PID được sử dụng lại liên tục). Những gì nó cung cấp cho bạn là một số sao cho, nếu người khác chạy tập lệnh của bạn, họ sẽ nhận được một mã định danh khác trong khi của bạn vẫn đang chạy. Khi máy của bạn chết, PID có thể được tái chế và người khác có thể chạy tập lệnh của bạn, nhận cùng một bộ mã và do đó có cùng tên tệp.

Như vậy, chỉ thực sự lành mạnh khi nói "$$ đưa ra một tên tệp sao cho nếu ai đó chạy cùng một kịch bản mà ví dụ của tôi vẫn đang chạy, họ sẽ nhận được một tên khác".


5

$$ là PID của bạn. Nó không thực sự tạo ra một tên tệp duy nhất, trừ khi bạn cẩn thận và không ai khác thực hiện chính xác như vậy.

Thông thường, bạn sẽ tạo một cái gì đó như / tmp / myprogramname $$

Có rất nhiều cách để phá vỡ điều này và nếu bạn viết thư đến các địa điểm thì những người khác có thể viết thư cho nhiều hệ điều hành để dự đoán những gì bạn sẽ có và xoay quanh - hãy tưởng tượng bạn đang chạy với quyền root và tôi tạo / tmp / yourprogname13395 dưới dạng một liên kết tượng trưng trỏ đến / etc / passwd - và bạn viết vào đó.

Đây là một điều xấu để làm trong một kịch bản shell. Nếu bạn sẽ sử dụng một tệp tạm thời cho một cái gì đó, bạn nên sử dụng một ngôn ngữ tốt hơn ít nhất sẽ cho phép bạn thêm cờ "độc quyền" để mở (tạo) tệp. Sau đó, bạn có thể chắc chắn rằng bạn không ghi đè lên một cái gì đó khác.


3

$$ là pid của quá trình shell hiện tại. Đó không phải là một cách tốt để tạo tên tệp duy nhất.


3

$$ là pid (process id) của trình thông dịch shell chạy script của bạn. Nó khác nhau đối với mỗi quy trình đang chạy trên một hệ thống tại thời điểm này, nhưng theo thời gian, pid quấn quanh và sau khi bạn thoát ra, sẽ có một quy trình khác với cùng một pid. Miễn là bạn đang chạy, pid là duy nhất với bạn.

Từ định nghĩa ở trên, rõ ràng là cho dù bạn sử dụng $$ bao nhiêu lần trong một tập lệnh, nó sẽ trả về cùng một số.

Bạn có thể sử dụng, ví dụ /tmp/myscript.scratch.$$ làm tệp tạm thời của bạn cho những thứ không cần phải cực kỳ đáng tin cậy hoặc an toàn. Đó là một cách thực hành tốt để xóa các tệp tạm thời như vậy ở cuối tập lệnh của bạn, ví dụ: sử dụng lệnh bẫy:

trap "echo 'Cleanup in progress'; rm -r $TMP_DIR" EXIT

2

Đó là ID tiến trình của quy trình bash. Không có quy trình đồng thời sẽ có cùng một PID.


2

$$ là id quá trình của trình bao trong đó tập lệnh của bạn đang chạy. Để biết thêm chi tiết, xem trang man cho sh hoặc bash. Các trang man có thể được tìm thấy bằng cách sử dụng một dòng lệnh "man sh" hoặc bằng cách tìm kiếm trên web cho "shell manpage"


2

Hãy để tôi trả lời câu hỏi thứ hai của emk - đừng sử dụng $$ như một thứ "độc nhất". Đối với các tập tin, sử dụng mktemp. Đối với ID khác trong cùng một kịch bản bash, sử dụng "$$$ (date +% s% N)" cho một cách hợp lý cơ hội tốt của tính độc đáo.

 -k

0

Ngoài ra, bạn có thể lấy tên người dùng đăng nhập thông qua lệnh này. Ví dụ.

echo $(</proc/$$/login id). After that, you need to use getent command.
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.