Bash смернице

Да ли неко може да ми препоручи добар сајт, или књигу на тему bash скриптовања?
Већина ствари на које наилазим не дају објашњења за неке компликованије ствари. Типа ако желим функцију која узима више параметара, па је у њој нека петља или нешто:

function funkcija($arg1, $arg2, $arg3) { while [[ $arg1!=$arg2 && $arg1!=$arg2]]; do echo "trt-mrt" read $arg1 funkcija($arg1, $arg2, $arg3) done if [[ $arg1==$arg2 ]] then echo "trt-mrt-opet" fi else if [[ $arg1==$arg3 ]] then echo "nesto trece" fi else echo "nemam vise inspiracije" }

Куцкам псеудо код, наравно, јер немам појма како иде синтакса. Ова ф-ја горе, конкретно треба да узме одговор корисника (yes/no, односно y/n) као стринг, па ако је y или n нешто да изврши спрам одговора, а ако се не поклапа ни са једним од та два, да прикаже грешку и препоручи јевтин дактилографски курс.

Много је различитих упутстава тамо на интернету, а нека се чак и разликују по питању основних ствари. Типа:

if [[ $arg1==$arg2 ]] then

а може и:

if (( $arg1==$arg2 )) then

Такође, да ли иде тачка-зарез након “if” услова. Мада, негде сам прочитао да тачка зарез отвара под-процес у ком се та петља извршава. Слично оном пајповању (цевовању, негујмо српски језик) где постоје 3 варијанте (&, |, ; ). Сад, сувише сам то лабаво прешао, да бих се сетио свих детаља…

Па оно… препоручите :slight_smile:

Probaj ovde da nađeš:

Linux Shell Scripting Tutorial - A Beginner’s handbook

Симбол ; користиш као замену за размак. Пример:

if [[$PROMENLJIVA == 1234]] then echo "True" else echo "False" fi

if [[$PROMENLJIVA == 1234]] ; then echo "True" ; else echo "False" ; fi

Што се тиче литературе, препоручујем:
EnglishFrontPage - Greg’s Wiki
Welcome to The Grymoire! - sh, sed, grep, awk …

http://tldp.org/LDP/Bash-Beginners-Guide/html/

Ovako bi ta funkcija izgledaja

#!/bin/bash

function merac_pritiska(){
# Ovde se čita unos i smešta ga u promenljivu "odgovor"
read -r -p "Da li ste sigurni da hoćete merač pritiska? [D/n] " odgovor

# Provera sadržaja promenljive "odgovor"
# regularni izraz ^([dD])+$
if [[ "$odgovor" =~ ^([dD])+$ ]]; then
   echo "Kupujete. PRIZMA iz Kragujevca misli na vas."
elif [[ "$odgovor" =~ ^([nN])+$ ]]; then
   echo "Odustao, možda drugi put."
   exit 1
else
    echo "Greška u unosu"
    exit 1
fi
}

# Pozivanje funkcije "merac_pritiska"
merac_pritiska[/code]

Ako hoćeš da ograniš odgovor na [d/n], možeš da koristiš beskonačnu petlju iz koje se izlazi samo ako je odgovor d, D, n ili N.

[code]#!/bin/bash

function upitnik(){
  while true; do
    read -r -p "Da li ste sigurni da hoćete patike? [D/n] " REPLY
    case $REPLY in
      [dD])  return 0 ;;
      [nN])  return 1 ;;
      *) echo "Samo [D/n] su mogući odgovori!"
    esac
  done
}

upitnik
# smeštamo exit status "$?" funkcije "upitnik" u promenljivu odgovor
odgovor="$?"

if [[ $odgovor -eq 0 ]]; then
   echo "Kupujem."
elif [[ $odgovor -eq 1 ]]; then
   echo "Odustao, možda drugi put."
   exit
fi

echo "Kupio patike"

If [[ uslov ]]; then može da se napiše i ovako

If [[ uslov ]] then
tačka-zarez označava gde počinje novi red t.j. nova komanda

if [[ uslov ]] then echo 1; echo 2; echo 3 fi

if proverava da li je “exit status” nula.

Uzmimo na primer komandu “true” čiji je izlaz uvek 0. Otvori terminal i unesi

true; echo "$?"

Dok false uvek ima 1.

false; echo "$?"

Sledeći red će odštampati ok na ekranu

if true; then echo ok; fi

Ovaj red neće.

if false; then echo ok; fi

Ako hoćeš da ograniš odgovor na [d/n], možeš da koristiš beskonačnu petlju iz koje se izlazi samo ako je odgovor d, D, n ili N

Да, то сам и урадио (теоријски), са while петљом у функцији, која позива саму функцију док се један од два услова не испуне.

Што се тиче function upitnik() {…}, ту нешто дебело нисам разумео, а није везано само за bash. Пошто је цела ф-ја под while true, одговор који враћа 0 би требало поново да покрене петљу, што значи да ће се вртети бесконачно ако је одговор “да”, што нема смисла…

*) --ово је default, и ваљда враћа false(?)

Молим и објашњење за [dD]) и [nN]) o_O. Да ли прихвата унос који се поклапа са једним, било којим карактером који се налази под []), или ће да прихвати и унос ‘Dd’ или ‘dD’ или само ‘D’ или само ‘d’?

# regularni izraz ^([dD])+$

Верујем да ће одговор на претходно питање одговорити и за овај хијероглиф, односно то сад само служи за даље поређење.

Везано за exit 1. Ово сам нашао на нету:

Exit code 0 Success
Exit code 1 General errors,Miscellaneous errors, such as “divide by zero” and other impermissible operations
Exit code 2 Misuse of shell builtins (according to Bash documentation) Example: empty_function(){}

Овај случај разумем зашто иде exit 1:

else
    echo "Greška u unosu"
    exit 1
fi

Али зашто и овде exit 1, кад нема грешке? Само треба да да поруку за један од два валидна избора и настави својим путем…

elif [[ "$odgovor" =~ ^([nN])+$ ]]; then
   echo "Odustao, možda drugi put."
   exit 1

Скрипта прво позове функцију, а из функције се врађа назад када се дође до return наредбе. То значи да ће се извршавање функције прекинути онда када корисник унесе неки од симбола D, d, N, n. Када унесеш n, функција вради статус 0 и то се упише у променљиву одговор.

Што се тиче регуларних израза, они су наука за себе. Овај пример конкретно проверава да ли се на првом месту у промељивој налази d ili D (ако сам добро видео). Саветујем да озбиљно изучиш регуларне изразе, примењују се стално када се ради некаква обрада текста.

Скрипта прво позове функцију…

Јесте. Побрљавио сам мало у глави. Све јасно на ту тему.

Саветујем да озбиљно изучиш регуларне изразе

Мхм. Осим што употреба знакова уме да варира колико ја знам. Ал ајде, логика је иста.

Може ли се помоћу C језика направити програм који покреће неку .sh скрипту? Покушавам да направим нешто што наликује .exe фајлу у Винџи. Мрзи ме да отварам терминал и куцкам ./nesto.sh и chmod + x ( јел у GUI-у chmod оно кад ме пита “mark executable”? )

Da

Skriptu koja pokreće drugu skriptu možeš da startuješ i bez otvaranja terminala, a kroz alias možeš da postaviš sve što ti padne na pamet.
Npr, često koristim jedan glupavi alias malo kriptičnog naziva, ali meni vrši posao u terminalu:

alias tchmia='dch -c debian/changelog --force-distribution -D mia --no-auto-nmu'

alias/skripta prijavljuje grešku, ali mislim da je jasno kako to funkcioniše…
Screenshot - 08132018 - 05:26:21 PM.png

Да, али… Ову сам специјално наменио да ради одмах након инсталације и да копира неке теме за xfce и прави неопходне фолдере за све кориснике, мрзи ме да се бакћем с тим стварима. Алијас бих морао да додајем након инсталације. Мислио сам да функционише више као готов програмчић…
Еdit:
Сад ћу да видим шта каже, поткрале су ми се неке грешке у самој скрипти

Hm? zar nije bolje onda da napraviš rpm paket za to što tebi treba, ako već koristiš Suse?
Kroz SPEC file za rpm build možeš sve da definišeš…

Можда? Нисам дошао до тог нивоа још :D.
Покушавам да видим шта ми багује у овој скрипти

Jednom moraš to prelomiti…pravljenje .deb (ili .rpm, svejedno…) paketa je krajnje jednostavna stvar, treba samo koristiti dev skripte/alatke koje su odavno napravljene da olakšaju posao te vrste.
Npr:
How to create a GNU Hello RPM package - Fedora Project Wiki

Ма не кажем… Што да не :slight_smile: само идем једно по једно. Ако није фрка, треба ми мала помоћ око саме скрипте. Дакле треба да направи .themes директоријум у сваком home фолдеру, ма колико их има и како се звали, а потом прекопира фајлове које је претходно отпаковала и убаци све отпаковане фолдере у сваки .themes у сваком home диру ( леле ал га срочих ). За сада, скрипта прави .themes фолдере успешно тамо где треба, ал никако да прекопира отпакован садржај…
Одмах да напоменем, ово што пише “home/phq/Programming/fakeRoot/home/”, то је путања за тест полигон. Дакле fakeRoot је ту да замени прави root да не правим брљотине по систему… Сама скрипта би требало да је проста:

#! /bin/bash

## 13-08-2018
## Copy themes to all users

a=""
## otpakuje fajl i pamti gde je otpakovan
current_dir=$(pwd)
tar -xvzf nu_XFCE_pack.tar.gz
for dir in /home/phq/Programming/fakeRoot/home/*/; do
    cd $dir; mkdir .themes
## Ovaj deo (mislim) ne radi kako treba
    a=$("$dir"/.themes)
    cp -R $current_dir/"nu Xfce pack"/*/ $a/
done

Вероватно сам зезнуо неки симбол негде, још ми је нова ова синтакса.

Malo sam izmenio metodologiju, izbacio sam promenljivu “a”…skripta ulazi u user dir, pravi .themes folder, ulazi u taj folder, prekopira sadržaj, vraća se u ~/home, i tako redom, for petlja.
Naravno, i putanju sam promenio za testiranje kod mene, pa je ti vrati kako tebi odgovara…u principu je nevažno.
Sintaksu uporedi sa tvojom, par sitnica razlike ima, a i ja volim da telo petlje uredim pregledno…u velikim zagradama.

[CODE]#! /bin/bash

13-08-2018

Copy themes to all users

a=""

otpakuje fajl i pamti gde je otpakovan

current_dir=$PWD
tar -xvzf nu_XFCE_pack.tar.gz
for dir in /home/dragan/Desktop/fakeRoot/home/*/; do
{
cd $dir
mkdir .themes
cd .themes
cp -R $current_dir/“nu XFCE pack”/ .
cd …
}
done
[/CODE]

Screenshot - 08142018 - 12:08:39 AM.png

Волим и ја, ал на тему нигде нисам наишао да се заправо употребљава у bash-у.

Ок, бар сам био на добром путу. Једино не видим сврху cd… команде пред крај, кад ће ионако да врати у други директоријум у следећем обрту. Ископирано је. Само сам мало променио у:

cp -R $current_dir/"nu XFCE pack"/*/ .

ал то је то. За current_dir=$PWD нисам знао да може. Увек варијаблама којима додељујем излазну вредност неке команде стављам као var=$(some_command), но то су сад ситнице. Хвала :slight_smile:

@Prizma
Moje “znanje” o skriptama je prilično jadnjikavo, na početničkom nivou.
Ipak, razumem osnovne principe, pa su mi zgodne da rešim konkretan problem :slight_smile:
Ovo je primer kako je kroz skiptu “rešena” instalacija rEFInd u TRIOS-u, kada dotični treba da se instalira na UEFI…prosto ga prekopiram iz live iso, mrzelo me da pravim custom deb :slight_smile:
Skripta je ubačena u instaler, i radi ono čemu je namenjena :slight_smile:

[CODE]#!/bin/bash

Copyright © 2015 TRIOS project http://trios.rs

Dragan Kramar [email protected]

This script is licensed under GNU GPL version 2.0 or above

-------------------------------------------------------------------------

set e

sve što je potrebno za instalaciju refind već imamo u triosefi.img

dakle, prikopčamo triosefi.img pod /mnt, prekopiramo gde šta treba u target

mount -t auto -o loop /triosefi.img /mnt
cd /mnt
cp -r keys /boot/efi/
cd EFI
cp -r boot tools /boot/efi/EFI

izađemo iz /mnt i otkačimo ga

cd / && umount /mnt

zatim instaliramo efibootmgr i registrujemo refind u NVRAM

instalacija efibootmgr, za slučaj da nema mreže, može da se odradi i kroz support folder u iso

zajedno sa grub-efi paketima ?

apt update && apt install -y efibootmgr
efibootmgr -c -l \EFI\boot\grubx64.efi -L rEFInd

exit 0[/CODE]