bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: bash uses tmp files for inter-process communication instead of pipes


From: Linda Walsh
Subject: Re: bash uses tmp files for inter-process communication instead of pipes?
Date: Tue, 07 Oct 2014 15:03:43 -0700
User-agent: Thunderbird

Pierre Gaston wrote:
That's where you are wrong, there is no reason for *your* use case, but the
basic idea behind process substitution is to be able to use a pipe in a
place where you normally need a file name.
Well, that's not what I needed it for. I needed to read from a child process that changed directories. ----
How can you say there is no reason for my use case...

It's not thoroughly polished yet, but it does work. It can rename and reorder your
network interfaces on boot so you can keep them with consistent names and
ordering -- something systemd doesn't seem to support.  Furthermore, it
doesn't depend on any suse library code -- which they've been putting in
hooks and traps for those not using systemd.  Supposedly people not using
systemd won't be able to boot their systems. This is one of my side projects to keep my system booting and to make available
to anyone who might want to use it.  But you call that no reason?

Sigh.

IF you want to see what I was doing in context, its attached.
It's a stand alone script to tell you if your interfaces are in your
desired order, reorder them if you wish, and act as a startup/shutdown script to fix things each boot. I haven't spent any time in cleanup, but it's still
not bad code.  See if the code is not readable -- even for shell!




#!/bin/bash 
#boot.assign_network_names
### BEGIN INIT INFO
# Provides:           net-devices
# Required-Start:     boot.udev boot.device-mapper boot.localfs
# Required-Stop:      $null   
# Default-Start:       B
# Default-Stop:        
# Short-Description:   reorder and rename net devices
# Description:         reorder and rename net devs if needed
### END INIT INFO
#
# assign network names as rc-script
#       L A Walsh, (free to use/modify/distribute to nice people) (c) 2013-2014
#              
#include standard template:
_prgpth=${0:?}; _prgpth=${_prgpth#-} _prg=${_prgpth##*/}; 
_prgdr=${_prgpth%/$_prg}
[[ -z $_prgdr || $_prg == $_prgdr ]] && _prgdr="$PWD"
#if ! typeset -f include >&/dev/null ;then 
#       source ${_LOCAL_DIR:=/etc/local}/bash_env.sh;
#fi
export PATH="/etc/local/bin:/etc/local/lib:$PATH"
export 
PS4='>>${BASH_SOURCE:+${BASH_SOURCE[0]}}#${LINENO}${FUNCNAME:+(${FUNCNAME[0]})}>
 '


#include stdalias (needed entries included "inline", below)
shopt -s extglob expand_aliases

alias dcl=declare                                       sub=function 
alias int=dcl\ -i                                       map=dcl\ -A             
                hash=dcl\ -A            array=dcl\ -a
alias lower=dcl\ -l                             upper=dcl\ -u                   
string=dcl                      my=dcl
alias map2int=dcl\ -Ai          intArray=dcl\ -ia

cfg_fn="/etc/sysconfig/assign_netif_names"

[[ -f $cfg_fn ]] || {
        echo "Cannot find required config file: $cfg_fn"; exit 1; }

# expected variables to be read in
array needed_drivers
array Linknames
array Default
map if2hw

. $cfg_fn || { echo "Error in reading config file $cfg_fn"; exit 2; }

DfltRE="^+(${Default_good[@]})$"
DfltRE=${DfltRE// /|}

declare -a down_ln=()
for ln in "${Linknames[@]}"; do
        [[ $DfltRE =~ $ln ]] && continue;
        down_ln+=($ln)
done

map hw2if

for intf in "${!if2hw[@]}" ; do
        addr=${if2hw[$intf]}    
        hw2if[$addr]="$intf"
done


############# end read config ######

#include rc.status  -- essential funcs included below:
int rc_status=0
sub rc_reset { rc_status=0; }

sub rc_status { 
        rc_status=$?;
        if ((rc_status))  && { (($#)) && [[ $1 = -v ]] ; }; then
                echo "Abnormal rc_status was $rc_status." 
        elif (($#)) && [[ $1 = -v ]] ; then
                echo "rc_status: ok"
        fi
}

sub rc_exit {
        rc_status=$?;
        rc_status
        exit $rc_status
}

sub warn () { local msg="Warning: ${1:-"general"}"
        printf "%s" >&2 "$msg"
}

sub die () { int stat=$?; local msg="Error. ${1:-"unknown"}"
        echo "$msg (errno=$stat)" >&2
        (exit $stat);                                                           
                                        #sets $? (doesn't exit inside ()
        rc_status -v 
        rc_exit
        exit $stat                                                              
                                                # exit unless die called in 
subshell
}

sysfs=/sys
sysnet=$sysfs/class/net

[[ -d $sysfs && -d $sysnet ]] ||
sysnet=$sysfs/class/net
sys_modules=$sysfs/module

if [[ -z $(type -P modprobe) ]]; then   # verify find of modprobe
        export PATH=/bin:/sbin:/usr/bin:/usr/sbin:$PATH
fi

if [[ -n $(type -P modprobe) ]]; then   # if found, alias it
        alias modprobe="$(type -P modprobe)"
else                                                                            
                                                                # only throw 
error if needed
        alias modprobe="die 'cannot load required modules'"
fi

if [[ -z $(type -P ip ) ]]; then                                # ip is needed, 
so no delayed error
        die "Cannot find 'ip' util -- needed for network setup"
fi

alias ip="$(type -P ip)"


sub varflags() {                                                                
                                # util: get dcl flags of a var
        my var="${1:-""}"
        read out <<<$(declare -p "$var" )
        [[ $out =~ /^declare.*=.*$/ ]] || die "no such variable"
        out="${out%% +([^-])=*}"
        out="${out#declare }"
        [[ ${out:0:1} == - ]] || { echo ""; return 0 ; }
        echo "${out#-}"
}

sub isarray() {                                                                 
                                # util: chk if pass name is an array
        my name="${1:-""}"
        flags=$(varflags $name)
        [[ $flags =~ a ]] && return 0
        return 1
}

sub ipcmd () {                                  # unused/incomplete
        my ipcmd="${1:?}"; shift; array tmpbuff
        my outbuff="${2:-tmpbuff}"
}

sub rev () {                                            # reverse elements of a 
list, 1/iteration (recursive)
        (($#==0)) && { echo ""; return 0 ;}
        my element=${1:?}; shift;
        (($#==0)) && { echo "$element"; return 0;}
        echo "$(rev "$@") $element"
}

sub rename_if () {
        my old_name=${1:?} new_name=${2:?}
        echo ip link set name "$new_name" dev "$old_name"
}


sub down_if () {
        my if_name=${1:?}
        echo ip link set down dev "$if_name"
}

sub set_links_down() {                                                          
        # can't operate on up links
        for int in "${down_ln[@]}"; do
                down_if "$int" down
        done
}


sub vrfy_drivers () {
        int errors=0;
        for i in ${needed_drivers[@]} ; do
                if [[ ! -d $sys_modules/$i ]]; then     # check for loaded or 
static drivers
                        modprobe "$i" || {
                                warn "Module $i is not in kernel and can't be 
loaded"
                                errors+=1
                        }
                fi
        done
        return $errors
}



map act_hw2if                                                                   
                                        #actual values (to be read in)
map act_if2hw
map XIF                                                                         
                                                        #tmp array to hold 
exchanged IF's

sub get_net_IFnames_hwaddrs () {                                # get names + 
addrs from /sys
        vrfy_drivers
        array pseudo_devs=(br bond ifb team)
        string pseudo_RE="^+(${pseudo_devs[@]})$"
        pseudo_RE=${pseudo_RE// /|}
        string netdev_pat="+([_0-9a-z])+([0-9])"
        ( cd "$sysnet" && 
                for nm in $( echo $netdev_pat); do
      [[ $pseudo_re =~ $nm ]] && continue
                        hwaddr="$(<$nm/address)"
                        echo "$nm" "$(<$nm/address)"
                done )
}

sub read_actuals () {                                                           
                # parse output stream from above
        my ifname hwaddr
        while read ifname hwaddr; do
                act_hw2if[$hwaddr]="$ifname"
                act_if2hw["$ifname"]="$hwaddr"
        done < <(get_net_IFnames_hwaddrs)
}


sub ifaddr_cmd () {
        if ((${#act_hw2if[@]:-0}==0)) ;then read_actuals; fi
        my hwaddr
        for ifname in $(printf "%s\n" "${act_hw2if[@]}"|sort|tr "\n" " ") ; do
                my first_ifn="$ifname"
                if [[ $ifname =~ \+ ]] ; then 
                        first_ifn="${ifname%%+*}"
                fi
                printf "%s\t%s\n" "$ifname" "${act_if2hw["$first_ifn"]}"
        done
}

sub ifmap_cmd () {
        ifaddr_cmd "$@"
}       


sub remap_cmd () {                                                              
                        # remap devnames if needed
        if ((${#act_hw2if[@]}==0)); then read_actuals; fi
        my key ifname
        int count=0 

        array ifnames=$(printf "%s\n" "${!if2hw[@]}"|sort|
                                                                        grep -P 
'^[^~+]*$' |tr "\n" " ")

        array rev_ifns=($(rev "${ifnames[@]}" ))

        for key in "${rev_ifns[@]}"; do
                int is_regex=0;  
                ifname="$key"
                if [[ ${key:0:1} == ~ ]];then ifname=${key:1}; is_regex=1; fi

                my hwaddr="${if2hw["$key"]:-""}"

                my actual_hw="${act_if2hw["$ifname"]:-""}"

                my actual_if="${act_hw2if["$actual_hw"]:-""}"                   
##line 233

                if [[ ${actual_hw:-""} && ! $actual_hw =~ \+ ]]; then           
##
                        if ((is_regex)); then [[ $actual_hw =~  $hwaddr ]] && 
continue
                        else  [[ $actual_hw == $hwaddr ]] && continue;  fi

                        if [[ ! ${act_if2hw["$ifname"]:-} ]]; then
                                #Nobody has the name, use it
                                down_if "$actual_hw"
                                rename_if "$actual_hw" "$ifname" ; count+=1
                        else
                                rename_if "$actual_if" "X$ifname";      #don't 
count temp renames 2x
                                XIF["X$ifname"]="$hwaddr"
                        fi
                fi
        done
        if ((${#XIF[@]}==0)); then 
                echo "HW interfaces appear to be in order."; return 0; fi
        int count=0
        for ifname in "${!XIF[@]}"; do 
                hwaddr=${XIF[$ifname]}; 
                ifname=${ifname#X}
                my destname=${hw2if[$hwaddr]}
                rename_if "$ifname" "$destname" ; count+=1
        done
        printf "%d interface%s renamed\n" $count "$( (($count!=1)) && echo "s" 
)"
}

sub start_cmd () {
        remap_cmd "$@"
}

hash switches=([ifmap]=1 [remap]=1 [start]=1)

sub help () {
        echo "$_prg:"
        echo "Options: ifmap  - show current hw# -> IF map"
  echo "         remap  - verify & remap ifnames if needed"
        return 1
}


if (($#)) ; then 

        dcl op="${1#:-}"

        if [[ ${switches[$op]:-} ]]; then 
                cmd="${op}_cmd"
                shift
                $cmd "$@"
        else 
                echo "Unknown switch :-$op"
        fi
else 
        help
fi

# vim: ts=2 sw=2 number fdm=marker fdc=1

#/etc/sysconfig/assign_netif_names - sample config
# to be sourced by BASH
######
# assign_netif_names reads this at boot to learn of a users 
# desired network naming (and ordering)

#needed_drivers=(e1000e bnx2 ixgbe)      # (list builtin as well as modules)

# Note -- using brace_expansions
#Linknames=( $(echo eth{0..5}) )

# Links that we _expect_ will come up with right names (built-mods)
#Default_good=( $(echo eth{0..1}) )


# store as hash, with intfname as key and it's ethernet addr as the data
#       if2hw=([eth0]="00:15:17:bf:be:b2" [eth1]="00:15:17:bf:be:b3"
#                                [eth2]="00:26:b9:48:71:e2" 
[eth3]="00:26:b9:48:71:e4"
#                                [eth4]="a0:36:9f:15:c9:c0" 
[eth5]="a0:36:9f:15:c9:c2" )



reply via email to

[Prev in Thread] Current Thread [Next in Thread]