first rework of old scripts

This commit is contained in:
Matthias Hemmerich 2022-05-19 11:03:55 +02:00
parent c8d4f25cc9
commit 9434889cc1
5 changed files with 828 additions and 1 deletions

4
.secrets.env Normal file
View file

@ -0,0 +1,4 @@
SNIPEIT_APIKEY=
SNIPEIT_DOMAIN=
REPO=
BRANCH=

View file

@ -1,2 +1,59 @@
# compose
# compose your linux
This repo contains all files to modify the system after it has been installed.
Please make sure to create the file `.secrets.env` with the following content:
```
SNIPEIT_APIKEY= # https://snipe-it.readme.io/reference/generating-api-tokens
SNIPEIT_DOMAIN= # orga.z31.it
REPO= # The URL of the Repo were your want to get the angestoepselt-info info Script, like https://codeberg.org/angestoepselt/compose
BRANCH= # the Branach of the REPO, default at codeberg.org is main
```
```
Options:
INFO:
-h|--help print this info
-v|--version show version of script
-a|--all running all task below
-u|--update perform an basic system update
-i|--install install all packages for this system
-r|--register Register PC in snipe-IT Asset Management
-c|--configure running basic system config settings
-d|--files_download download useful files to your HomeDirectory
-m|--modify_dm paint your Desktop Manager with angestoepselt design
--checkinfo Check if PC is already in snipe-IT present
--clean clean up trash, like files and from system tasks like packagemanger
```
---
### Take care of snipeIT Custom fields at system_register
```
{
"status_id": "2",
"name": "$Model",
"model_id": "$model",
"serial": "$serialno",
"_snipeit_mac_address_1": "$HW_ADDRESS",
"_snipeit_betriebssystem_2": "$Distro",
"_snipeit_festplatte_4": "$HDD",
"_snipeit_prozessor_5": "$CPU",
"_snipeit_arbeitsspeicher_6": "$Memory",
"_snipeit_optisches_laufwerk_7": "$Optical_Drive",
"_snipeit_display_8": "$display",
"_snipeit_akku_9": "$Battery_life",
"_snipeit_anydeskid_10": "$Anydesk_ID"
}
```
### fetch all informations about Custom Fields with an API request
```
export $(cat .secrets-env) && \
curl --silent --request GET --url "https://$SNIPEIT_DOMAIN/api/v1/fields" --header 'accept: application/json' --header 'authorization: Bearer '$SNIPEIT_APIKEY'' | jq .rows[].db_column_name
```

249
angestoepselt-info Normal file
View file

@ -0,0 +1,249 @@
#!/bin/bash
# This ist a small script which collect system information of a Linux PC and print it as json
# created by matthias of angestöpselt e.V.
# created at 2022-02-17
version=1.0
charity=angestoepselt
os=Linux
read_uname() {
read -ra uname <<< "$(uname -srm)"
kernel_name="${uname[0]}"
kernel_version="${uname[1]}"
kernel_machine="${uname[2]}"
}
get_memory() {
while IFS=":" read -r a b; do
case $a in
"MemTotal") ((mem_used+=${b/kB})); mem_total="${b/kB}" ;;
"Shmem") ((mem_used+=${b/kB})) ;;
"MemFree" | "Buffers" | "Cached" | "SReclaimable")
mem_used="$((mem_used-=${b/kB}))"
;;
"MemAvailable")
mem_avail=${b/kB}
;;
esac
done < /proc/meminfo
mem_total="$((mem_total / 1024))"
mem_total=$(awk '{printf "%.2f", $1 / $2}' <<< "$mem_total 1024")
mem_label=GiB
memory="${mem_total}${mem_label:-MiB}"
}
get_cpu() {
# Get CPU name.
cpu_file="/proc/cpuinfo"
cpu="$(awk -F '\\s*: | @' \
'/model name|Hardware|Processor|^cpu model|chip type|^cpu type/ {
cpu=$2; if ($1 == "Hardware") exit } END { print cpu }' "$cpu_file")"
# Remove un-needed patterns from cpu output.
cpu="${cpu//(TM)}"
cpu="${cpu//(tm)}"
cpu="${cpu//(R)}"
cpu="${cpu//(r)}"
cpu="${cpu//CPU}"
cpu="${cpu//Processor}"
cpu="${cpu//Dual-Core}"
cpu="${cpu//Quad-Core}"
cpu="${cpu//Six-Core}"
cpu="${cpu//Eight-Core}"
cpu="${cpu//[1-9][0-9]-Core}"
cpu="${cpu//[0-9]-Core}"
cpu="${cpu//, * Compute Cores}"
cpu="${cpu//Core / }"
cpu="${cpu//(\"AuthenticAMD\"*)}"
cpu="${cpu//with Radeon * Graphics}"
cpu="${cpu//, altivec supported}"
cpu="${cpu//FPU*}"
cpu="${cpu//Chip Revision*}"
cpu="${cpu//Technologies, Inc}"
cpu="${cpu//Core2/Core 2}"
# Remove CPU brand from the output.
cpu="${cpu/AMD}"
cpu="${cpu/Intel}"
cpu="${cpu/Core? Duo}"
cpu="${cpu/Qualcomm}"
cpu="${cpu//[[:space:]]}"
}
get_disk() {
type -p df &>/dev/null ||
{ err "Disk requires 'df' to function. Install 'df' to get disk info."; return; }
df_version=$(df --version 2>&1)
# Create an array called 'disks' where each element is a separate line from
# df's output. We then unset the first element which removes the column titles.
IFS=$'\n' read -d "" -ra disks <<< "$(df "${df_flags[@]}" "${disk_show[@]:-/}")"
unset "disks[0]"
# Stop here if 'df' fails to print disk info.
[[ ${disks[*]} ]] || {
err "Disk: df failed to print the disks, make sure the disk_show array is set properly."
return
}
for disk in "${disks[@]}"; do
# Create a second array and make each element split at whitespace this time.
IFS=" " read -ra disk_info <<< "$disk"
disk=$((disk_info[${#disk_info[@]} - 5] / 1024/ 1024))G
done
}
get_model() {
if [[ -d /system/app/ && -d /system/priv-app ]]; then
model="$(getprop ro.product.brand) $(getprop ro.product.model)"
elif [[ -f /sys/devices/virtual/dmi/id/board_vendor ||
-f /sys/devices/virtual/dmi/id/board_name ]]; then
model=$(< /sys/devices/virtual/dmi/id/board_vendor)
model+=" $(< /sys/devices/virtual/dmi/id/board_name)"
elif [[ -f /sys/devices/virtual/dmi/id/product_name ||
-f /sys/devices/virtual/dmi/id/product_version ]]; then
model=$(< /sys/devices/virtual/dmi/id/product_name)
model+=" $(< /sys/devices/virtual/dmi/id/product_version)"
elif [[ -f /sys/firmware/devicetree/base/model ]]; then
model=$(< /sys/firmware/devicetree/base/model)
elif [[ -f /tmp/sysinfo/model ]]; then
model=$(< /tmp/sysinfo/model)
fi
# Remove dummy OEM info.
model=${model//To be filled by O.E.M.}
model=${model//To Be Filled*}
model=${model//OEM*}
model=${model//Not Applicable}
model=${model//System Product Name}
model=${model//System Version}
model=${model//Undefined}
model=${model//Default string}
model=${model//Not Specified}
model=${model//Type1ProductConfigId}
model=${model//INVALID}
model=${model//All Series}
model=${model//<2F>}
case $model in
"Standard PC"*) model="KVM/QEMU (${model})" ;;
OpenBSD*) model="vmm ($model)" ;;
esac
}
get_vendor() {
sys_vendor=$(cat /sys/devices/virtual/dmi/id/sys_vendor)
}
get_distro() {
source /etc/os-release
distro="${NAME} ${VERSION_ID}"
}
get_serial() {
[ `id -u` -eq 0 ] && serialno=$(sudo cat /sys/devices/virtual/dmi/id/product_serial)
}
get_category() {
category=$(hostnamectl | grep Chassis | cut -c 21-)
}
get_odd() {
[[ $(lsblk --include 11 -n) ]] && odd="1" || odd="0"
}
get_mac() {
mac=$(ip link | sed -n "/BROADCAST.*state UP/{n;p}" | tail -1 | tr -s " " | cut -d" " -f3)
}
get_anydesk_id() {
dpkg-query -l "anydesk" &>/dev/null && anydesk_status="TRUE" || anydesk_status="FALSE"
if [ "$anydesk_status" == "TRUE" ]; then
# fetching the id of anydesk consumes most of the time when calling the script. Room for improvement
andydesk_id=$(/usr/bin/anydesk --get-id)
fi
}
get_battery() {
for bat in /sys/class/power_supply/*; do
if [[ $bat =~ BAT ]]; then
source $bat/uevent
energy_full_design="$(< "${bat}/energy_full_design")"
energy_full="$(< "${bat}/energy_full")"
battery=`expr ${energy_full} \* 100 / ${energy_full_design}`%
fi
done
}
get_resolution() {
resolution=$(xdpyinfo | awk '/dimensions/ {print $2}')
}
get_display() {
display=`xrandr | awk '/ connected/{print sqrt( ($(NF-2)/10)^2 + ($NF/10)^2 )/2.54}' | cut -c -2 | head -n 1`
}
get_desktopmanager() {
echo $XDG_CURRENT_DESKTOP
}
# fetch informations
read_uname
get_memory
get_cpu
get_disk
get_model
get_vendor
get_distro
get_serial
get_category
get_odd
get_mac
get_desktopmanager
get_anydesk_id
# fetch additional laptop infos
if [[ $category == "laptop" ]]; then
get_battery
get_resolution
get_display
fi
# print summary in json
printf '{\n'
printf ' %s\n' "\"Charity\": \"${charity}\"",
printf ' %s\n' "\"Distro\": \"${distro}\"",
printf ' %s\n' "\"Vendor\": \"${sys_vendor}\"",
printf ' %s\n' "\"Model\": \"${model}\"",
printf ' %s\n' "\"Serial\": \"${serialno}\"",
printf ' %s\n' "\"Platform\": \"${category}\"",
printf ' %s\n' "\"CPU\": \"${cpu}\"",
printf ' %s\n' "\"Memory\": \"${memory}\"",
printf ' %s\n' "\"HDD\": \"${disk}\"",
printf ' %s\n' "\"HW_ADDRESS\": \"${mac}\"",
printf ' %s\n' "\"Anydesk_ID\": \"${andydesk_id}\"",
printf ' %s\n' "\"Resolution\": \"${resolution}\"",
printf ' %s\n' "\"Displaysize\": \"${display}\"",
printf ' %s\n' "\"Battery_life\": \"${battery}\"",
printf ' %s\n' "\"Optical_Drive\": \"${odd}\"",
printf ' %s\n' "\"Version\": \"${version}\""
printf '}\n'

515
late_command.sh Normal file
View file

@ -0,0 +1,515 @@
#!/bin/bash
# Install and configure a Ubuntu-PC for the charity organization angestöpselt e.V. | angestoepselt.de
# created by matthias of angestöpselt e.V.
# created at 2022-02-17
version=0.2
set -o errexit
exec 100>/tmp/z31.lock || exit 1
flock 100 || exit 1
# Speed up script by not using unicode.
LC_ALL=C
LANG=C
# some static variables
DEBIAN_FRONTEND=noninteractive
current_user=$(id 1000 | awk -F '[()]' '{print $2}')
lockfile=/tmp/z31.lock
sysinfofile=$HOME/.config/systeminfo.json
random_tmpdir=$(mktemp)
SCRIPT_DIR="$(dirname "$0")"
TIME=$(date +%Y%m%d%H%M)
LOGTIME=$(date "+%Y-%m-%d %H:%M:%S")
LOGFILE="$SCRIPT_DIR/$TIME-z31.log"
# Set variables for stdout print
COLOR_N='\e[0m'
COLOR_GREEN='\e[1;32m'
COLOR_RED='\e[1;31m'
COLOR_BLUE='\e[1;34m'
COLOR_WHITE='\e[1;97m'
OK="[${COLOR_GREEN}ok${COLOR_N}]"
FAIL="[${COLOR_RED}fail${COLOR_N}]"
INFO="[${COLOR_BLUE}info${COLOR_N}]"
SKIP="[${COLOR_BLUE}skip${COLOR_N}]"
PROGRESS="[${COLOR_BLUE}..${COLOR_N}]"
# log actual command and it's stderr to logfile in one go
runcmd_stdout() {
echo "+ $1" >>"$LOGFILE"
bash -c -o pipefail "$1" 2>>"$LOGFILE" | tee -a "$LOGFILE"
}
runcmd() {
echo "+ $1" >>"$LOGFILE"
bash -c -o pipefail "$1" >>"$LOGFILE" 2>&1
}
printprog() {
echo -ne "${PROGRESS} $*\r"
}
printok() {
echo -e "\r${OK} $*"
}
printfail() {
echo -e "\r${FAIL} $*"
}
printinfo() {
echo -e "${INFO} $*"
}
printskip() {
echo -e "\r${SKIP} $*"
}
ErrorHandling() {
set -eu
printfail "Something went wrong, exiting. Check $LOGFILE for more details."
}
system_update() {
set -o pipefail
trap ErrorHandling ERR INT
printprog "update cache"
runcmd "sudo /usr/bin/apt-get update -qq"
printok "update cache"
printprog "upgrade system"
runcmd "sudo /usr/bin/apt-get dist-upgrade -y -qq"
printok "upgrade system"
}
system_install_base() {
set -o pipefail
trap ErrorHandling ERR INT
printprog "add anydesk repo to source.list.d"
if [ -f "/etc/apt/sources.list.d/anydesk-stable.list" ]; then
printskip "add anydesk repo to source.list.d"
else
runcmd "sudo /usr/bin/wget -qO - https://keys.anydesk.com/repos/DEB-GPG-KEY | sudo apt-key add - && \
echo "deb http://deb.anydesk.com/ all main" > /etc/apt/sources.list.d/anydesk-stable.list"
printok "add anydesk repo to source.list.d"
fi
echo ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula select true | sudo debconf-set-selections
printprog "install apt packages (this can take some time)"
runcmd "sudo /usr/bin/apt-get install --yes -qq -o Dpkg::Options::=--force-confdef --ignore-missing \
ubuntu-restricted-extras \
apt-transport-https \
vlc \
gdebi \
gparted \
tlp \
language-pack-de-base \
libreoffice \
libreoffice-l10n-de \
libreoffice-help-de \
libreoffice-help-en-gb \
libreoffice-l10n-en-gb \
firefox \
firefox-locale-de \
firefox-locale-en \
thunderbird \
thunderbird-locale-de \
thunderbird-locale-en \
thunderbird-locale-en-gb \
gimp \
anydesk \
libqt5qml5 \
language-selector-common \
openoffice.org-hyphenation \
language-pack-kde-ar \
language-pack-kde-uk \
language-pack-kde-ru \
language-pack-kde-fa"
printok "install apt packages"
}
system_install_edubuntu() {
set -o pipefail
trap ErrorHandling ERR INT
# Edubuntu packages (official support until 18.04) https://wiki.ubuntuusers.de/Edubuntu_Programme
printprog "install Edubuntu packages (this can take some time)"
runcmd "sudo /usr/bin/apt-get install --yes -qq -o Dpkg::Options::=--force-confdef --ignore-missing \
blinken \
calibre \
cantor \
chemtool \
dia \
einstein \
fritzing \
gamine \
gcompris \
goldendict \
inkscape \
kalgebra \
kalzium \
kanagram \
kbruch \
kgeography \
khangman \
kig \
klettres \
kmplot \
kstars \
ktouch \
ktuberling \
kturtle \
kwordquiz \
laby \
lightspeed \
lybniz \
marble \
melting \
parley \
pencil2d \
ri-li \
rocs \
step \
tuxmath \
tuxpaint \
tuxtype \
yorick"
printok "install Edubuntu packages"
}
system_clean() {
set -o pipefail
trap ErrorHandling ERR INT
printprog "clean up apt cache and packages"
runcmd "sudo /usr/bin/apt-get autoremove --yes"
printok "clean up apt cache and packages"
}
system_configure() {
set -o pipefail
trap ErrorHandling ERR INT
printprog "set timezone"
runcmd "timedatectl set-timezone Europe/Berlin"
printok "set timezone"
}
system_files_download() {
set -o pipefail
trap ErrorHandling ERR INT
printprog ""
runcmd ""
printok ""
}
system_modify_dm() {
set -o pipefail
trap ErrorHandling ERR INT
# TODO: detect dm of device and choose modification
# cat /etc/X11/default-display-manager > /usr/sbin/gdm3 (Gnome Desktop Manager)
# goals to cover
# - Wallpaper
# -
printprog ""
runcmd ""
printok ""
}
system_checkinfo() {
set -o pipefail
trap ErrorHandling ERR INT
# this part checks if the device is already registered in snipe-IT
# is already registered it returns 1
# this is a new device it returns 0
if [ ! -f $sysinfofile ]; then
printprog "write systeminfo to $sysinfofile"
runcmd "mkdir /home/$current_user/.config/angestoepselt && /bin/bash /usr/local/bin/angestoepselt-info > $sysinfofile"
printok "write systeminfo to $sysinfofile"
fi
printprog "read systeminfo"
runcmd "jq -e . $sysinfofile >/dev/null 2>&1"
printok "read systeminfo"
HW_ADDRESS=$(cat $sysinfofile | jq -r .HW_ADDRESS)
ASSET_TAG=$(cat $sysinfofile | jq -r .Asset_Tag)
## start localcheck
if [[ $ASSET_TAG =~ ^[0-9]+$ ]]; then
printinfo "already in Snipe $ASSET_TAG"
return 1
elif
[ -f $SCRIPT_DIR/mac_white.list ] && grep -Fxq "$HW_ADDRESS" mac_white.list
then
unset HW_ADDRESS
printinfo "Device is using a charity owned USB Ethernet-Adapter"
return 1
## end localcheck
else
## start snipe-it check
printprog "check presence of snipe-IT API"
runcmd "curl -o /dev/null --silent https://$SNIPEIT_DOMAIN"
printok "check presence of snipe-IT API"
printinfo "fetch info from Snipe-IT"
result=$(curl --silent --request GET \
--url "https://$SNIPEIT_DOMAIN/api/v1/hardware?limit=1&search=${HW_ADDRESS//[:]/%3A}" \
--header 'accept: application/json' \
--header 'authorization: Bearer '$SNIPEIT_APIKEY'')
[[ $(echo $result | jq '(has("error"))') == true ]] && { printinfo "$(echo $result | jq .error)"; return 1; }
system_check_result=$(echo $result | jq .total) # doesn't work
asset_tag=$(echo $result | jq -r .rows[].asset_tag)
if [ -n "$asset_tag" ]; then
printinfo "Device already present in Snipe-IT: RE$asset_tag"
printprog "add ASSET_TAG to $sysinfofile"
runcmd "jq '. |= . + {"Asset_Tag": \"'${asset_tag}'\"}' $sysinfofile > $random_tmpdir/systeminfo.json.tmp && mv $random_tmpdir/systeminfo.json.tmp $sysinfofile"
printok "add ASSET_TAG to $sysinfofile"
else
printok "Device not in Snipe-IT"
system_checkinfo_value="newdevice"
return 0
fi
## end snipe-it check
fi
}
system_register() {
set -o pipefail
trap ErrorHandling ERR INT
if [[ "$system_checkinfo_value" != "newdevice" ]]; then
printskip "register Device at Snipe-IT"
fi
# is snipe-IT reachable?
printprog "check presence of snipe-IT API"
runcmd "curl -o /dev/null --silent https://$SNIPEIT_DOMAIN"
printok "check presence of snipe-IT API"
# convert json to variables, like key=value
eval "$(jq -r '. | to_entries | .[] | .key + "=" + (.value | @sh)'< $sysinfofile)"
printinfo "fetching variables for register $Platform at Snipe-IT"
# get platform. at the moment this looks for a laptop in string. If ist not a laptop it is a desktop PC (model 2)
[[ "$Platform" == *"laptop"* ]] && { model=1; display="$Displaysize @ $Resolution"; } || model=2
# clean up anydesk variable. > room for improvement, only integer should be in the var. This can be handled in the angestoepselt-info script
[[ "$Anydesk_ID" == *"SERVICE_NOT_RUNNING"* ]] && unset Anydesk_ID
# cannont locate issue with true and false, simple workaround to fix it
[[ "$Optical_Drive" == "FALSE" ]] && Optical_Drive=nein || Optical_Drive=ja
# change this variables used in this post to your needs, read the README of this repo and read ahead in the Snipe-IT API docs for more Informations
# https://snipe-it.readme.io/reference/updating-custom-fields
post_data()
{
cat <<EOF
{
"status_id": "2",
"name": "$Model",
"model_id": "$model",
"serial": "$serialno",
"_snipeit_mac_address_1": "$HW_ADDRESS",
"_snipeit_betriebssystem_2": "$Distro",
"_snipeit_festplatte_4": "$HDD",
"_snipeit_prozessor_5": "$CPU",
"_snipeit_arbeitsspeicher_6": "$Memory",
"_snipeit_optisches_laufwerk_7": "$Optical_Drive",
"_snipeit_display_8": "$display",
"_snipeit_akku_9": "$Battery_life",
"_snipeit_anydeskid_10": "$Anydesk_ID"
}
EOF
}
printprog "register $Platform at Snipe-IT"
post_result=$(curl --silent --request POST \
--url 'https://'$SNIPEIT_DOMAIN'/api/v1/hardware' \
--header 'accept: application/json' \
--header 'authorization: Bearer '$SNIPEIT_APIKEY'' \
--header 'Content-Type: application/json' \
--data "$(post_data)")
post_status=$(echo $post_result |jq -r .status)
post_message=$(echo $post_result |jq -r .message)
asset_tag=$(echo $post_result |jq -r .payload.asset_tag)
if [ "$post_status" = "success" ]; then
printok "register $Platform at Snipe-IT"
printprog "add PC to $sysinfofile"
runcmd "jq '. |= . + {"Asset_Tag": \"'${asset_tag}'\"}' $sysinfofile > $random_tmpdir/systeminfo.json.tmp && mv $random_tmpdir/systeminfo.json.tmp $sysinfofile"
printok "add PC to $sysinfofile"
else
printfail "$post_message"
fi
}
script_check_root() {
set -o pipefail
trap ErrorHandling ERR INT
printprog "check root privileges"
runcmd "[ $(id -u) -eq 0 ]"
printok "check root privileges"
}
script_check_snipesecrets() {
set -o pipefail
trap ErrorHandling ERR INT
printprog "check .secrets.env"
runcmd "[ -f $SCRIPT_DIR/.secrets.env ] && export $(cat $SCRIPT_DIR/.secrets.env)"
printok "check .secrets.env"
}
script_prerequisites() {
set -o pipefail
trap ErrorHandling ERR INT
printinfo "install requirements"
printprog "install required packages"
runcmd "sudo /usr/bin/apt-get -qq --yes install jq moreutils dialog html2ps python3 python3-pip curl wkhtmltopdf"
printok "install required packages"
printprog "install angestoepselt-info"
runcmd "sudo /usr/bin/wget quiet $REPO/raw/branch/master/angestoepselt-info -O /usr/local/bin/angestoepselt-info && sudo chmod +x /usr/local/bin/angestoepselt-info"
printok "install angestoepselt-info"
}
usage() {
printf "%s" "\
Usage: $0 --option
Options:
INFO:
-h|--help print this info
-v|--version show version of script
-a|--all running all task below
-u|--update perform an basic system update
-i|--install install all packages for this system
-r|--register Register PC in snipe-IT Asset Management
-c|--configure running basic system config settings
-d|--files_download download useful files to your HomeDirectory
-m|--modify_dm paint your Desktop Manager with angestoepselt design
--checkinfo Check if PC is already in snipe-IT present
--clean clean up trash, like files and from system tasks like packagemanger
"
exit 1
}
POSITIONAL_ARGS=()
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
usage
;;
-u|--update)
script_check_root
system_update
shift
shift
;;
-i|--install)
script_check_root
system_install_base
system_install_edubuntu
shift
shift
;;
--clean)
script_check_root
system_clean
shift
shift
;;
--charity)
charity=${OPTARG:=angestoepselt}
shift
shift
;;
-c|--configure)
script_check_root
system_configure
shift
shift
;;
-d|--files_download)
system_files_download
shift
shift
;;
-m|--modify_dm)
script_check_root
system_modify_dm
shift
shift
;;
--checkinfo)
script_check_snipesecrets
system_checkinfo
shift
shift
;;
-r|--register)
script_check_snipesecrets
system_register
shift
shift
;;
-a|--all)
script_check_root
system_update
system_install
system_clean
system_configure
system_files_download
system_modify_dm
script_check_snipesecrets
system_checkinfo
system_register
exit 0
;;
-v|--version)
printf '%s\n' "$0 v$version"
exit 1
;;
-*|--*)
echo "Unknown option $1"
usage
exit 1
;;
*)
POSITIONAL_ARGS+=("$1")
shift
;;
esac
done
set -- "${POSITIONAL_ARGS[@]}" # restore positional parameters
if [[ -n $1 ]]; then
echo "Last line of file specified as non-opt/last argument:"
tail -1 "$1"
fi

2
mac_white.list Normal file
View file

@ -0,0 +1,2 @@
# mac white list for USB Adapter
# these mac will be ignored during snipe check