1

I am trying to write a script and at some point i needed to list all the things in a directory and grep someting from that directory. I can't do it with ls. ls is not my guy to do it. So i tried to do ls' job with echo command instead , but it is giving me a permission denied error now. You can see the script below :

#!/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

And i am getting this error :

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

What can i do to complete this script ? Is there a way to get the listing of a directory and pipe it with something. Also even i could get rid of that permission then i think echo will cause more trouble to me.

EDIT : I tried to replace echo with find command , here is the results and errors.

#!/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
6
  • What about find command? Jul 27, 2018 at 10:24
  • 4
    $(/sys/class/net/*) is a command substitution - it is trying to execute the files in /sys/class/net Jul 27, 2018 at 10:26
  • In find command it is getting the directory itself for me. e.g. if i write find /sys/class/net/ it will bring me /sys/class/net/ /sys/class/net/ra0 etc... I don't want that /sys/class/net/ part
    – Ugur Akgul
    Jul 27, 2018 at 10:27
  • You could use a simple shell glob for interface in /sys/class/net/* and check for / exclude lo within the body of the loop Jul 27, 2018 at 10:30
  • Can you be more spesific ?
    – Ugur Akgul
    Jul 27, 2018 at 10:35

3 Answers 3

5

You seem to want to query the carrier files under /sys/class/net/*/ to see if there is at least one that indicates whether you're online or not (ignoring */lo/carrier).

With a shell loop:

#!/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

Using 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

Or, as a bash "almost-one-liner"

#!/bin/bash

shopt -s extglob

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

This last one assumes that the files hold a single digit 1 if that carrier is online and that there is no data, or at least no 1, if it's not.

The loops above (using read) will read the first line only from each carrier file until a 1 is found.


The issue in your code is the command substitution $(/sys/class/net/*) which will try to execute the first matching filename as a command with the other matching filenames as arguments.

Also, the test [ $OnLine ] would be "true" whenever $OnLine is non-empty. I'm not sure what the files that you parse contains if the carrier is not on-line, but even a zero would be taken as "true" here.

7
  • In sh version , you are checking the carrier after the for loop , so it is not working. When i try to implement it inside the for loop , i get bad number error.
    – Ugur Akgul
    Jul 27, 2018 at 12:32
  • @UgurAkgul I'm unfamiliar with these files. What do they contain if the carrier is not on-line?
    – Kusalananda
    Jul 27, 2018 at 12:33
  • It has a value like 1 , or 0. I don't know the reason behind bad number error. Carrier is telling us that , the network interface is up.
    – Ugur Akgul
    Jul 27, 2018 at 12:37
  • @UgurAkgul It would give that error if the thing it's reading is not a number. Try changing the -eq to = and -ne to != to do string comparisons instead. (I'm leaving the screen for a couple of hours, but I'll sort it out properly later).
    – Kusalananda
    Jul 27, 2018 at 12:39
  • I tried to make things simple and after the if statement added an else statement. This is doing good so far. I'm sure i will be having problems about this.
    – Ugur Akgul
    Jul 27, 2018 at 12:48
2

How about these one-liners. i.e. have grep specifically exclude the loopback.

GNU grep

Note : requires GNU grep dated March 2001 or later. Specifically doesn't work on the BusyBox grep bundled in OpenWRT.

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

Solution suitable for older GNU grep versions and non-GNU grep

e.g. BusyBox versions.

grep -x 1 /dev/null /sys/class/net/*/carrier|grep -qv /lo/ || ! echo 'not online' >&2
3
  • --exclude option doesn't working.
    – Ugur Akgul
    Jul 27, 2018 at 10:50
  • Old version of linux ?
    – steve
    Jul 27, 2018 at 10:55
  • 1
    openWRT distro of linux :)
    – Ugur Akgul
    Jul 27, 2018 at 10:58
-2

you can try to execute the above script in sudo mode

$sudo su

"execute your script here"

1
  • I am running with root access all the time.
    – Ugur Akgul
    Jul 27, 2018 at 11:01

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .