このスクリプトの何が問題なのでしょうか?

このスクリプトの何が問題なのでしょうか?

そこで私はこのガイドからこのスクリプトを入手しました: 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 条件は false になりますが、このスクリプトの実行中に「このスクリプトを実行するには root である必要があります。」というメッセージが表示されます。

また、元のスクリプトでは、このif条件は次のように指定されていました。

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

しかし、どうやら -ne は文字列にのみ使用されるため、不正な数値エラーが発生したため、!= に変更しました。

答え1

代わりに、

sh script.sh

実行する

bash script.sh

(または、#!/bin/bashインタープリターを設定する最初の行として追加します)。

shUbuntuのシェルはない bashですが、 と呼ばれる別のシェルがありますdashdashは ほど多くの機能を持たないためbash、より効率的ですが、これらの機能が不足しているため、 向けのスクリプトが機能しなくなることがありますbash。そのような機能の1つは $UID、変数です。定義されていませんdash

つまり、スクリプトが で実行されるとdash、比較は となり["" != "0"]、どのユーザーが実行しているかに関係なく true と評価されます。ただし、 でルート権限を使用して実行されるとbash、文字列は等しくなり、スクリプトは機能します。

答え2

としてマクラヴィンは言う、自動的に設定される読み取り専用UID(およびEUID)変数は、bash(および他のシェル)。これは標準ではありませんボーンスタイルのシェルこれらの変数を設定することはsh想定できません。特にshUbuntuでは(現在、デフォルトでは)dash、設定されません。

次の 2 つのオプションがあります。

  1. スクリプトがbashではなくによって実行されるようにしますsh
  2. スクリプトを変更して、移植性を高め、 を必要としないようにしますbash

スクリプトを実行するbash

スクリプトの名前を教えてくれませんでした(大丈夫です)。cleanup、これは、作業中のガイド内の同様のスクリプトの名前です。

特に私がないのように呼びますcleanup.sh。これは、接尾辞付きの名前を付けることをお勧めしないためです.sh

  • 接尾辞.shは、 と互換性があることを示しますsh
  • ほとんどのスクリプトにはサフィックスがまったく付けられておらず、.shまたは.bashサフィックスが付いていると、ファイルが「トップレベル」スクリプトではなく「ライブラリ」であると解釈されることもあります。つまり、実際に直接実行されるのではなく、他のスクリプトによってソースされるコード (たとえば、.組み込みスクリプトを使用) が提供されるということです。

ただし、.shサフィックスを追加しても、スクリプトの技術的な動作にはまったく影響しません。サフィックスを追加しても、技術的な利点や欠点はありません。

追加ハッシュバンラインスクリプトの最初の行として:#!/bin/bash

スクリプトを実行可能にすると。chmod +x cleanup

今ならできるスクリプトを実行する次のコマンドを実行します:

  • ./cleanup、現在のディレクトリにある場合。(特に、教育、調査、テスト、楽しみ、またはその他の限定的または 1 回限りの使用のためにスクリプトを作成する場合、これがおそらく最も一般的な方法です。)

  • /path/to/cleanup一般的には です。コマンドの最初の単語に が含まれている場合、/それは実行可能ファイルへのパスとして解釈されます。(これが上記の構文の理由です./。 は.現在のディレクトリを意味します。)

    による最初の単語最初のコマンドまで(最初のコマンドは含まない)逃げられないスペースまたはタブ:
    foo-bar/bazは の最初の単語ですfoo-bar/baz quxが、 はspam\ hamの最初の単語です。これは、spam\ ham eggsその前のスペースhamがバックスラッシュでエスケープされているためです。

  • cleanup、それがあなたのディレクトリ内にある場合PATH(そして最初にリストされたディレクトリに同じ名前の実行ファイルが存在せず、それがシェル組み込み関数、 またはエイリアス)。

スクリプトの有無にかかわらずcleanupハッシュバン行#!...またはその行の内容は次のとおりです。

  • sh cleanupshインタープリターとして実行しようとします。
  • bash cleanupbashインタープリターとして実行しようとします。

これは、これらのケースでは、実際にインタープリタ (shまたはbash) を実行し、実行するスクリプトの名前をインタープリタに渡すためです。多くのプログラムは、コマンドラインで開くファイル名を受け入れ、 や などのシェルはshこのbash規則に従います。

スクリプトをポータブルにする

スクリプトを移植可能にしたい場合、最も簡単な方法は、 を$UIDまったく使用せず、代わりにすべての Bourne スタイルのシェルで利用可能な機能を使用することです。

一般的に、ユーザーIDを決定するための組み込みシェル機能はありません。しかし、idこれはシェルの組み込みプログラムではなく外部プログラムですが、catそしてls、それが存在すると予想するのは合理的です。

id単独では大量の情報が出力されますが、id -u有効なユーザー ID のみが提供されます。

したがってif [ "$UID" != "$ROOT_UID" ]、 の代わりに、以下を使用できます。

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

技術的には、これは同等ではありません。$UIDではbash実際のユーザー ID が提供され、実際には のid -uに対応します。 EUID ではなく UID が必要な場合は、 を使用します。bash$EUIDid -ru

関連情報