Làm thế nào kịch bản của tôi có thể xác định liệu nó đang được chạy bởi bash hay dash?


13

Tôi đang chạy bản cài đặt Oneiric mới (không phải là bản nâng cấp) trên hai hệ thống khác nhau và chạy vào cùng một tập hợp các vấn đề dường như có liên quan.

Điều khó chịu nhất trong số đó là, khi tôi sử dụng .profile và .bashrc mà tôi đã mang theo từ Mac OS X, đăng nhập vào X qua LightDM sẽ đăng xuất ngay lập tức. Tôi tin rằng điều này được gây ra bởi thực tế là, khi chạy "/ bin / sh", nó hoạt động như / bin / dash, nhưng vẫn có biến $ SHELL được đặt thành / bin / bash.

Phép ngoại suy

Tôi có một số lượng lớn .bashrc. Bạn có thể thấy nó ở đây nếu bạn muốn, nhưng nội dung của nó có thể không liên quan, ngoài thực tế là nó chứa đầy sự bashism, và thực tế là nó hoạt động không có lỗi bên trong xterm hoặc trên bảng điều khiển ảo.

My .profiletrông như thế này (viết tắt):

case $SHELL in 
*bash*)
    if [ -f $HOME/.bashrc -a -r $HOME/.bashrc ]; then
        . $HOME/.bashrc
    fi
    ;;
esac

Nếu tôi cố đăng nhập vào X qua LightDM, nó sẽ đăng nhập lại ngay lập tức. Tôi gặp lỗi .xsession-errorsliên quan đến .bashrc của tôi trông như thế này (viết tắt):

/home/mrled/.bashrc: 103: [[: not found
[: 103: Linux: unexpected operator
[: 274: -P :: unexpected operator
/home/mrled/.bashrc: 520: complete: not found

Như tôi đã nói, khi tôi chạy bash từ bảng điều khiển ảo, tôi không gặp phải những lỗi này. Hơn nữa, nếu tôi loại bỏ .profile của mình, tôi có thể đăng nhập vào X tốt. (Tôi cũng có thể đăng nhập vào bảng điều khiển ảo và sử dụng startxđể bắt đầu phiên X hoạt động, nhưng tất nhiên đây không phải là giải pháp lâu dài.)

Tuy nhiên, tôi phát hiện ra rằng nếu tôi chạy /bin/sh -l, tôi sẽ gặp lỗi. Đây là một phiên ví dụ (lưu ý: dấu nhắc bash tôi đã đơn giản hóa bash>và dấu nhắc sh chỉ là $):

bash> echo $SHELL
/bin/bash
bash> echo $BASH_VERSION
4.2.10(1)-release
bash> /bin/sh -l
/home/mrled/.bashrc: 103: [[: not found
[: 103: Linux: unexpected operator
[: 274: -P :: unexpected operator
/home/mrled/.bashrc: 520: complete: not found
$ echo $SHELL
/bin/bash
$ echo $BASH_VERSION

$

Q1: Tại sao điều này xảy ra?

Tôi hiểu rằng / bin / sh bây giờ trỏ đến dấu gạch ngang thay vì bash , nhưng nếu đó là sự thật, thì tại sao $SHELLvẫn quay trở lại /bin/bash?

Q2: Tôi có thể làm gì để giải quyết nó?

Có cách nào để làm việc này? Tôi muốn giữ hồ sơ của mình tải .bashrc để tôi có được môi trường giống nhau trên cả vỏ đăng nhập và không đăng nhập, nhưng rõ ràng tôi chỉ muốn nó tải cho bash, chứ không phải / bin / sh giả mạo như bash.

Bạn có thể nhận thấy sự khác biệt trong nội dung của các biến $ BASH_VERSION ở trên. Tôi đã thử gói .profile của mình vào một cái gì đó như thế này:

if [ -n $BASH_VERSION ]; then
    # the rest of my .profile as above
fi

Tuy nhiên, -nkiểm tra chỉ trả về đúng nếu độ dài của chuỗi khác không, tuy nhiên, mặc dù trong phiên ở trên, khi tôi chạy dưới /bin/sh -lnó sẽ trả về một chuỗi trống cho $ BASH_VERSION, khi nó được bao gồm trong .profile của tôi như thế này , nó vượt qua bài kiểm tra! Họ tiến hành tìm nguồn .bashrc của tôi và đưa ra các lỗi giống như trước đây.

Bây giờ tôi thực sự bối rối.


Lưu ý rằng dash -lcũng cho thấy $SHELLcó giá trị /bin/bash.
Scott Severance

3
$SHELLlà bất cứ điều gì lĩnh vực cuối cùng trong /etc/passwd(hoặc getent passwd) nói.
Tạm dừng cho đến khi có thông báo mới.

@DennisWilliamson Cảm ơn bạn , đó là những gì tôi cần biết để tìm câu trả lời đúng.
Micah R Ledbetter

Bạn đang làm sai. Bạn nên đặt môi trường không dành riêng cho ~/.profilebash, những thứ dành riêng cho bash ~/.bashrcvà có ~/.bash_profilecả nguồn.
nyuszika7h

Câu trả lời:


12

Bạn có thể làm cho thực tế $BASH_VERSIONlà trống trong dashcông việc cho bạn:

if [ "$BASH_VERSION" = '' ]; then
    echo "This is dash."
else
    echo "This is bash."
fi

2
Kỹ thuật "x" là cổ xưa và chỉ cần trong vỏ cổ . Sử dụngif [ "$BASH_VERSION" = '' ]
Tạm dừng cho đến khi có thông báo mới.

@DennisWilliamson: Cảm ơn. Tôi đã nghĩ rằng kỹ thuật của bạn là dành riêng cho Bash, nhưng tôi chỉ dừng lại ở Dash và nó đã hoạt động. Tôi đã chỉnh sửa câu trả lời của mình.
Scott Severance

Hoặc chỉ sử dụng-n , hoặc không có gì . (+1, mặc dù. = ''Hoạt động hoàn toàn tốt.)
Eliah Kagan

5

Bạn chỉ cần sử dụng dấu ngoặc kép trên biến BASH_VERSIONđể sử dụng-n

if [ -n "$BASH_VERSION" ];then
 echo "this is bash"; 
else 
 echo "this is dash";
fi

1
kể từ khi [ "$EMPTY_STRING" ]đánh giá sai, bạn thậm chí không cần -n. Bạn chỉ cần trích dẫn các biến.
jeberle 11/03/2016

2

Sử dụng /proc/[PID]/cmdlineđể xem tập lệnh đang được chạy với cái gì và kiểm tra xem nó chứa cái gì. Các $$biến sẽ cho chúng ta những PID của vỏ chạy. Vì vậy, chúng ta có thể tạo ra một kịch bản như thế này,

#!/bin/bash
if grep -q 'bash' /proc/$$/cmdline ;
then
    echo "This is bash"
else
    echo "This is some other shell"
fi

Đây là một thử nghiệm của cùng một kịch bản:

$> bash test_script.sh                                                                                                
This is bash
$> dash test_script.sh                                                                                                
This is some other shell

Điều này sẽ không hoạt động trên Mac. Kiểm tra $ BASH_VERSION.
Austin Burk

2
@AustinBurk nó không cần phải hoạt động trên Mac. Đây là hỏi Ubuntu.
TheWanderer

@ Zacharee1 ôi trời ơi, tôi không chú ý :,)
Austin Burk

Tôi không muốn chỉnh sửa điều này khỏi những gì bạn dự định, nhưng tôi khuyên bạn nên đề cập đến những hạn chế của phương pháp này. Bash không cần phải có bashtên của nó; Không có gì lạ khi bashthực thi được chạy qua một liên kết tượng trưng với tên khác. Thông thường người ta vẫn muốn xem xét Bash đó. Ngoài ra, mẫu được khớp ở bất cứ đâu trong/proc/$$/cmdline đó, có thể sửa được, nhưng hãy nhớ rằng các đối số trong cmdlineđược phân tách bằng ký tự null. grep -qE '(^|/)bash$'cảm thấy như nó nên hoạt động nhưng cho kết quả dương tính giả khi có bất kỳ đối số nào bash.
Eliah Kagan

@EliahKagan Hãy thoải mái chỉnh sửa câu trả lời của tôi bất cứ lúc nào - bạn có đủ chuyên môn để tôi biết các chỉnh sửa của bạn chỉ có thể cung cấp các cải tiến. Câu trả lời được viết khi tôi xanh hơn nhiều với vỏ sò so với bây giờ.
Sergiy Kolodyazhnyy
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.