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
  • What about find command? – Ipor Sircer Jul 27 '18 at 10:24
  • 4
    $(/sys/class/net/*) is a command substitution - it is trying to execute the files in /sys/class/net – steeldriver Jul 27 '18 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 '18 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 – steeldriver Jul 27 '18 at 10:30
  • Can you be more spesific ? – Ugur Akgul Jul 27 '18 at 10:35
4

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.

  • 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 '18 at 12:32
  • @UgurAkgul I'm unfamiliar with these files. What do they contain if the carrier is not on-line? – Kusalananda Jul 27 '18 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 '18 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 '18 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 '18 at 12:48
1

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
  • --exclude option doesn't working. – Ugur Akgul Jul 27 '18 at 10:50
  • Old version of linux ? – steve Jul 27 '18 at 10:55
  • 1
    openWRT distro of linux :) – Ugur Akgul Jul 27 '18 at 10:58
-2

you can try to execute the above script in sudo mode

$sudo su

"execute your script here"

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.