這個腳本有什麼問題?

這個腳本有什麼問題?

所以我從本指南中得到了這個腳本:www.tldp.org/LDP/abs/abs-guide.pdf

LOG_DIR=/var/log
ROOT_UID=0
LINES=50
E_XCD=86
E_NOTROOT=87

if [ "$UID" != "$ROOT_UID" ]
then
echo "Must be root to run this script."
exit $E_NOTROOT
fi

if [ -n "$1" ]
then
lines=$1
else
lines=$LINES
fi

cd $LOG_DIR

if [ 'pwd' != "$LOG_DIR" ]
then
echo "Can't change to $LOG_DIR."
exit $E_XCD
fi

現在我在終端機上執行了 sudo su 並回顯 $UID,這給了我 0。運行此腳本時。

同樣在原始腳本中,此 if 條件給出為

if [ "$UID" -ne "$ROOT_UID" ]

但我收到非法數字錯誤,因為顯然 -ne 僅用於字串,所以我將其更改為 !=。

答案1

而不是執行它

sh script.sh

執行它

bash script.sh

(或新增#!/bin/bash為第一行來設定解釋器)。

shUbuntu 中的 shell是不是 bash,但是有一個名為 的單獨 shell dashdash沒有與 一樣多的功能bash,這使得它更加高效,但這些缺失的功能有時會破壞用於bash.其中一個特徵就是 $UID變量,它是沒有定義的dash

這意味著當腳本在 中執行時dash,比較將變為["" != "0"],無論哪個使用者執行它,其計算結果都是 true。但是,如果以 root 權限運行bash,則字串將相等,並且腳本將正常工作。

答案2

作為麥克洛文 說,自動設定的唯讀UID(和EUID)變數是bash(以及其他一些外殼)。這不是標準的伯恩風格的貝殼並且sh不能假設設定這些變數。特別sh是,在 Ubuntu 中(目前預設)dash,這不會設定它們。

您有兩個選擇:

  1. 使您的腳本運行bash而不是sh.
  2. 更改您的腳本,使其更加可移植並且不需要bash.

運行你的腳本bash

您還沒有告訴我們您的腳本的名稱(沒關係)。我要稱呼它為cleanup,因為這是您正在使用的指南中類似腳本的名稱。

特別注意的是我是不是稱為類似的東西cleanup.sh。這是因為我不建議您使用後綴命名它.sh

  • 後綴.sh表示它與sh!
  • 大多數腳本根本沒有後綴,並且具有.sh.bash後綴甚至可能被解釋為表明您的文件是“庫”而不是“頂級”腳本。也就是說,它提供由其他腳本(例如,使用.內建腳本)獲取的程式碼,而不是實際直接運行。

但是,包含.sh後綴不會以任何方式影響腳本的技術行為。這樣做沒有任何技術優勢或劣勢。

添加一個哈希棒線作為腳本的第一行:#!/bin/bash

使您的腳本可執行和。chmod +x cleanup

現在你可以運行你的腳本透過運行命令:

  • ./cleanup,當它位於當前目錄中時。 (特別是在為教育、探索、測試、娛樂或其他有限或一次性用途編寫腳本時,這可能是最常見的方式。)

  • /path/to/cleanup, 一般來說。如果命令的第一個字包含 a,則/它被解釋為可執行檔的路徑。 (這就是上述語法的原因./,as.表示當前目錄。)

    經過第一個字我的意思是命令直到但不包括它的第一個未逃脫的space 或 tab:
    foo-bar/baz是 的第一個單詞foo-bar/baz quxspam\ ham而是的第一個單詞,spam\ ham eggs因為前面的空格ham是用反斜線轉義的。

  • cleanup,如果它位於您的目錄中PATH(並且首先列出的目錄沒有同名的可執行文件,並且它沒有被外殼內置,功能, 或者別名)。

不管有沒有劇本cleanup有一個#!...hashbang 行或該行所說的內容:

  • sh cleanup仍將(嘗試)sh作為解釋器來運行它。
  • bash cleanup仍將(嘗試)bash作為解釋器來運行它。

這是因為,在這些情況下,您實際上正在執行解釋器(shbash)並將腳本的名稱傳遞給解釋器以執行。許多程式接受要在命令列上開啟的檔案名,並且 shell 喜歡shbash遵循此約定。

使您的腳本可移植

如果您想要讓腳本可移植,最簡單的方法是$UID根本不使用,而是使用所有 Bourne 風格 shell 都可用的一些工具。

一般來說,沒有內建的 shell 工具來確定使用者 ID。但你可以使用id。這是一個外部程式而不是內建的 shell,但就像catls,有理由預期它會出現。

id它本身會輸出一堆訊息,但id -u只給出有效的使用者 ID。

因此if [ "$UID" != "$ROOT_UID" ],您可以使用:

if [ "$(id -u)" != "$ROOT_UID" ]

從技術上來說,這不等價。$UIDinbash給予真實的使用者 ID,並且id -u確實對應於bashs $EUID。如果您確實想要 UID 而不是 EUID,請使用id -ru.

相關內容