web-dev-qa-db-ja.com

エコー許可が拒否されました(シェルスクリプトでlsコマンドの代わりにechoを使用しようとしています)

スクリプトを作成しようとしていますが、ある時点で、ディレクトリ内のすべてのものを一覧表示し、そのディレクトリからgrepを実行する必要がありました。 lsではできません。 lsはそれをする私の男ではありません。だから私は代わりにechoコマンドでlsの仕事をしようとしました、しかしそれは私に今許可拒否エラーを与えています。以下のスクリプトを見ることができます:

#!/bin/sh
# Test for network connection

for interface in $(echo $(/sys/class/net/*) | grep -v lo);
do
  if [ "$(cat /sys/class/net/"$interface"/carrier)" = 1 ]; then
 OnLine=1;
 fi
done
if ! [ $OnLine ]; then echo "Not Online" > /dev/stderr;
 exit;
fi

そして、私はこのエラーが発生しています:

./carriercontrol.sh: line 10: /sys/class/net/apcli0: Permission denied

このスクリプトを完了するにはどうすればよいですか?ディレクトリのリストを取得し、それを何かとパイプする方法はありますか?また、私でさえその許可を取り除くことができたので、エコーは私にもっと問題を引き起こすと思います。

EDIT: echoをfindコマンドに置き換えようとしました。結果とエラーは次のとおりです。

#!/bin/sh


# Test for network conection
for interface in $(find /sys/class/net -mindepth 1 | grep -v lo);
do
  if [ "$(cat /sys/class/net/"$interface"/carrier)" = 1 ]; then
 OnLine=1;
 fi
done
if ! [ $OnLine ]; then echo "Not Online" > /dev/stderr;
 exit;
fi

cat: can't open '/sys/class/net//sys/class/net/ra0/carrier': No such file or directory
cat: can't open '/sys/class/net//sys/class/net/eth0/carrier': No such file or directory
cat: can't open '/sys/class/net//sys/class/net/br-lan/carrier': No such file or directory
cat: can't open '/sys/class/net//sys/class/net/eth0.1/carrier': No such file or directory
cat: can't open '/sys/class/net//sys/class/net/apcli1/carrier': No such file or directory
cat: can't open '/sys/class/net//sys/class/net/apcli0/carrier': No such file or directory
1
Ugur Akgul

_/sys/class/net/*/_の下のcarrierファイルにクエリを実行して、オンラインかどうかを示すファイルが少なくとも1つあるかどうかを確認したいようです(_*/lo/carrier_は無視してください)。

シェルループの場合:

_#!/bin/sh

online=0
for carrier in /sys/class/net/*/carrier; do
    case "$carrier" in
        */lo/carrier) continue ;;
    esac

    if read online <"$carrier" && [ "$online" -eq 1 ]; then
        break
    fi
done

if [ "$online" -ne 1 ]; then
    echo 'not online' >&2
    exit 1
fi
_

bashの使用:

_#!/bin/bash

shopt -s extglob

online=0
for carrier in /sys/class/net/!(lo)/carrier; do
    if read online <"$carrier" && [ "$online" -eq 1 ]; then
        break
    fi
done

if [ "$online" -ne 1 ]; then
    echo 'not online' >&2
    exit 1
fi
_

または、bash "almost-one-liner"として

_#!/bin/bash

shopt -s extglob

grep -qx 1 /sys/class/net/!(lo)/carrier || ! echo not online >&2
_

この最後の1つは、そのキャリアがオンラインでデータがない場合はファイルが1桁の_1_を保持し、そうでない場合は少なくとも_1_がないことを前提としています。

上記のループ(readを使用)は、_1_が見つかるまで、各carrierファイルから最初の行のみを読み取ります。


コードの問題は、コマンド置換$(/sys/class/net/*)です。これは、最初に一致するファイル名をコマンドとして実行し、他の一致するファイル名を引数として実行しようとします。

また、テスト_[ $OnLine ]_は、_$OnLine_が空でない場合は常に「true」になります。キャリアがオンラインでない場合、解析するファイルに何が含まれているかはわかりませんが、ここではゼロでも「真」と見なされます。

4
Kusalananda

これらのワンライナーはどうですか。つまり、grepにループバックを明確に除外させます。

GNU grep

注:requires GNU grep2001年3月以降 。特にOpenWRTにバンドルされているBusyBox grepでは機能しません。

grep -q --exclude '/sys/class/net/lo/carrier' 1 /sys/class/net/*/carrier || echo "not online" >&2

古いGNU grepバージョンおよび非GNUgrepに適したソリューション

例えばBusyBoxのバージョン。

grep -x 1 /dev/null /sys/class/net/*/carrier|grep -qv /lo/ || ! echo 'not online' >&2
1
steve