A szövegszerkesztő – vi

Ma egy szövegszerkesztőről van egy körülbelüli elképzelésünk. Na a vi nem ilyen. 🙂

A vi <filenév> paranccsal indul a szövegszerkesztő. Ilyenkor alapban parancs módban vagyunk. 🙂 Billentyűkkel lehet eljutni a szerkesztői módba. Szerkeszteni ugyanis szerkesztői módban lehet. 🙂 “O” (shift+o) billentyűvel egy új sort szerkeszthetünk az aktuális pozíció fölött – ezek között a nyilakkal közlekedhetünk, esetleg “:<sorszám>“-mal, parancs módban. “o” billenyűvel az aktuális pozíció alatt nyílik új sor. “i” betűvel az aktuális pozícióban tudunk beszúrni szöveget, “a” betűvel hozzáfűzhetünk szöveget az aktuális pozíciótól (append). 🙂 Szerkesztői módból az “esc” billentyűvel tudunk parancs módba visszalépni.

Hogy ez miért jó? Mert szinte minden terminálban, bármely UNIX és Linux rendszerben installálva van vagy installálható. Egyébként nem muszáj használni (“:h” -val segítség kérhető, amiből “:q“-val lehet kilépni :)). Van az editor vagy nano, ami jobb műkedvelőknek. Az ctrl szekvenciákkal vezérelhető. 🙂 Hogy mégis miért jó? A jó programozó tud vi-ban, akár osztott ablakban, szintaxis-kiemeléssel, kizárólag billentyűk lenyomásával akármit írni (!).

Nézzük tovább a használatot. Kilépés, ha nem módosítottunk – ellenkező esetben hibaüzenetet kapunk – a “:q“, kilépés módosítások elvetésével “:q!“. Kilépés mentéssel “:wq” vagy “shift+zz“. 🙂

Nem írnám le a teljes kezelést, az szorgalmi++. 🙂 Még részleteznék pár apróságot. Hogyan lehet keresni? Egész egyszerűen parancs módban “/<keresendő_sztring>” – “n” betűvel lehet lépkedni előre, “shift+n“-nel visszafelé a találatok között. Még fontos lehet az “undo”, visszavonás funkció, ez egész egyszerűen az “u” parancs. Egy sort a “dd” paranccsal tudunk törölni. Három sort “3dd” paranccsal. 🙂 Jó, nem?

Akkor nézzük a továbbiakban felsorolásszerűen.

Ugrás a sor végére: “$
Ugrás a sor elejére: “0
Beolvas egy file-t. és beszúrja az adott pozcióba: “:r <filenév>
Képernyő megosztása: “:split <filenév>
Képernyő függőleges megosztása: “:vsplit <filenév>
Navigáció a két osztott képernyő között: “ctrl+ww
Sor másolása: másolás: “yy” (yank), kivágás: “dd” (delete), beillesztés pozíció előtt: “P“, pozíció után: “p” (paste)
Kijelölés másolásra karakterenként: “v“, soronként: “V“, utána “y” vagy “d“, végül “p” vagy “P” a beillesztéshez, osztott képernyők között is működik 🙂
File vége: “shift+g“, eleje “g
Egy szó előre: “w“, hátra: “b

És akkor beszéljünk még egy dologról. Minden editor tudja a keresés és cserét. Nézzük meg ezt vi-ban. A parancs formátuma a következő: “:%s/<keresendő>/<cserélendő>/“, illetve ha minden sorban többször előfordulhat a keresendő és cserélendő sztring, akkor “:%s/<keresendő>/<cserélendő>/g” – a végén van egy “g“. Itt említeni illik a keresett kifejezéssel kapcsolatban az ún. reguláris kifejezéseket (reguar expressions). Ez az a formátum, ahogyan a keresendő sztring megadható. A sed parancs egyébként ugyanilyen formátummal működik, file(ok)-ban cserél sztringeket. (A sztring karakterfüzér.) RegExp részletek az alábbi link alatt. 🙂

http://vbence.web.elte.hu/regex_leiras.html

A végére még egy “elvetemült” dolog. 🙂 Lehet a bash shell-ünket is vi módban használni. Egyébként pl. az előző parancs előhozására a fel nyilat használhatjuk. Igazából a fel/le nyilakkal kereshetünk az előzőleg beírt parancsok között, sőt: a shell-ünk el is menti a .bash_history file-ba az előzőleg beírt parancsainkat, így ha újra kinyitjuk a shell-t is emlékezni fog a parancsainkra. 🙂 Fontos funkcionalitás még “sima” shell-ben az ugrás a sor elejére “ctrl+a“, sor végére “ctrl+e“, továbbá aktuális parancs megszakítása “ctrl+c“. De mi is az a vi módú shell? A home könyvtáramban létrehoztam a .inputrc file-t, a következő tartalommal.

gvamosi@gergo1:~$ cat .inputrc
set editing-mode vi

Újra “beléptem” a shell-be (kilépés ctrl+d-vel, és újraindítás). Innentől az “esc” billentyűvel parancsmódba kerülünk, vi parancsmódba. Minden ugyanúgy működik, ahogy vi-ban. Ez tényleg csak a legkeményebb admin-oknál van így beállítva. 😉

És hogy hogy lehet a szintaxis kiemelést (syntax highlight) bekapcsolni? Nálam, a Debian 10-ben elég egyszerűen. Nézzük.

gvamosi@gergo1:~$ sudo apt-get install vim
..
gvamosi@gergo1:~$ which vi
/usr/bin/vi
gvamosi@gergo1:~$ l /usr/bin/vi
lrwxrwxrwx 1 root root 20 Aug 26 2017 /usr/bin/vi -> /etc/alternatives/vi
gvamosi@gergo1:~$ l /etc/alternatives/vi
lrwxrwxrwx 1 root root 18 Oct 2 00:12 /etc/alternatives/vi -> /usr/bin/vim.basic

Telepítés (install) után az alapértelmezett vi editor a vim lesz, amiben a szintaxis kiemelés bekapcsolt. 🙂 Vi IMproved, a programmer’s text editor.

Fork-bomba (és harakiri) :)

Ma az alábbi scriptről lesz szó, ami nemes egyszerűséggel a fork_bomb.sh nevet kapta. Arra való, hogy padlóra vigye a Linux vagy UNIX rendszert. Ha egy szülő folyamat egy gyermek folyamatot indít, fork történik. Ez a “bomba” saját magát indítja el újra meg újra. Ez egyébként csúnya dolog ebben a formában. 🙂

gvamosi@gergo1:~$ cat fork_bomb.sh
#!/bin/sh
#
# fork test by gvamosi on 2019-09-29
############################################

var1=0
if [ -n "$1" ]; then
var1=$1
fi
echo "$0 $var1"
var1=$((var1 + 1))

while true; do
sleep 2
/bin/sh $0 $var1 & # itt történik a rekurzív hívás, a "fork"
done

Hogy hogyan lehet elindítani?

gvamosi@gergo1:~$ ./fork_bomb.sh &

És leállítani, ha még nem késő? Két másodpercre vettem a sleep-jét, hogy legyen idő beavatkozni. A Linux-unk ugyan korlátozza az egy felhasználó által nyitható processzek számát, de egy másodperces sleep-pel a notebook-omat sikerült úgy megfektetnem, hogy csak a “szentháromság” (ctrl+alt+del) segített. Ugyanis hiába zárja be az operációs rendszer a processzeket, a rekurzív fork miatt újra és újra nyílnak a kis programocskák, így egy tartós leterhelt állapot keletkezik. Ilyenkor nem, vagy csak alig reagál a számítógépünk.

gvamosi@gergo1:~$ killall fork_bomb.sh
gvamosi@gergo1:~$ killall sh

Ez a két parancs segíthet, ebben a sorrendben, ha elég gyorsak vagyunk. 🙂

Utólag nézem, hogy a “kill -9 -1” – ilyet azért root-ként (rendszergazdaként) vagy dba-ként (adatbázis-adminisztrátorként) be ne írjunk, adatvesztés történhet! – úgy kivágta a saját processz-erdőmet egy szemvillanás alatt, hogy öröm volt nézni. 🙂 Megteszi reboot helyett, még jó, hogy a chrome böngészőmben van “restore” funkció a tabfülekre. 🙂

Egyébként a rendelkezésre álló “javakról” az ulimit parancs segítségével tájékozódhatunk.

gvamosi@gergo1:~$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 30575
max locked memory (kbytes, -l) 65536
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 30575
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited

Jól látható, hogy 1024-nél több fork_bomb.sh-t nem igen indíthatunk. A rendszergazda így simán tökön tud rúgni minket, ha garázdálkodunk. Régebben egyébként használtak az adminok ún. “watchdog” démont, ami automtikusan reboot-olta a rendszert, ha nagy volt a baj. 🙂

Van még egy érdekes parancs. Ez a root-ként (rendszergazdaként) kiadott “rm -rf /“. Rákérdezés nélküli rekurzív törlés a gyökérből kiindulva. Használata szigorúan TILOS!!! Letöröl MINDENT a DISZKRŐL!!! VÉGLEGESEN!!! Ezt a parancsot csak egyszer adhatjuk ki. 😦

Zombi-gyilkolás :)

A folyamatok státusza a top parancs képernyője szerint lehet “running” – “futó“, “sleeping” – “alvó“, “stopped” – “megállított“, illetve “zombie” – “zombi“.

A tegnapi secure shell-es lecke megírása közben véletlenül lehajtottam a Linux notebook képernyőjét, azaz összecsuktam a gépet. Közben az asztali Mac mini-ről bejelentkezve maradtam.

Ilyenkor egy bennragadt shell processzről van szó. Majdhogynem zombi. Persze valójában nem az. Zombit ugyanis nem lehet kill-elni, mivel a zombi processz már “halott”. Akkor tűnik el a processztáblából, ha a szülő processzét kinyírtuk. 🙂

A szülő processz id-ket ps all vagy céltudatosabban a ps -A -ostat,pid,ppid paranccsal írhatjuk ki. Ez utóbbinál az ostat ha z vagy Z, akkor van szó zombi processzről, a pid a processz azonosító, a ppid pedig a szülő folyamaté. Bővebben az alábbi linken lehet erről olvasni.

https://stackoverflow.com/questions/16944886/how-to-kill-zombie-process

Hogy hogyan lőttem ki kill -9-cel a bennragadt bash processzt, lásd az alábbiakban.

gvamosi@gergo1:~$ w
23:56:28 up 2 days, 13:11, 2 users, load average: 1.16, 0.91, 0.94
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
gvamosi tty2 tty2 Sat10 2days 1:39m 11.13s /opt/google/chrome/chrome --type=renderer --field-trial-handle=15503761646981189628,17074726826077816693,131072 --lang=en-US --enable-auto-reload
gvamosi pts/1 192.168.0.113 18:21 5:35m 0.00s 0.00s -bash
gvamosi@gergo1:~$ ps axu | grep bash
gvamosi 5312 0.0 0.0 7300 3612 pts/0 Ss Sep14 0:00 -bash
gvamosi 26716 0.0 0.0 6076 876 pts/0 S+ 23:56 0:00 grep bash
gvamosi 32208 0.0 0.0 7188 3884 pts/1 Ss+ 18:21 0:00 -bash
gvamosi@gergo1:~$ kill -9 32208
gvamosi@gergo1:~$ ps axu | grep bash
gvamosi 5312 0.0 0.0 7300 3612 pts/0 Ss Sep14 0:00 -bash
gvamosi 27005 0.0 0.0 6076 884 pts/0 S+ 23:56 0:00 grep bash
gvamosi@gergo1:~$ w
23:56:56 up 2 days, 13:12, 1 user, load average: 1.04, 0.90, 0.93
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
gvamosi tty2 tty2 Sat10 2days 1:39m 11.14s /opt/google/chrome/chrome --type=renderer --field-trial-handle=15503761646981189628,17074726826077816693,131072 --lang=en-US --enable-auto-reload
gvamosi@gergo1:~$

A w paranccsal megnéztem, hogy pts/1-en “benn maradtam” a szerverként szolgáló notebook-on gvamosi felhasználó név alatt (2 users). Utána ps paranccsal megkerestem azt a bash shell-t, ami szintén a pts/1-hez van rendelve. Ezután elég volt egy kill -9 PID – processz azonosító, azaz kill -9 32208 parancs. Jól látható az utána kiadott w parancs után, hogy eltűnt a “bennragadt” felhasználó (1 user). 🙂

Prompt – PS1 környezeti változó – mit is jelent a terminál ablakban vagy szöveges terminálban megjelenő gvamosi@gergo1:~$ prompt jel?

Az egész rendszerre érvényes, belépéskor automatikusan végrehajtott parancsok és beállítások helye a /etc/profile, ami rendszergazdaként, vagyis root user-ként (felhasználóként) szerkeszthető. Csak a prompt-beállítás szempontjából fontos részeket idézem.

gvamosi@gergo1:~$ cat /etc/profile

if [ "${PS1-}" ]; then
if [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then
# The file bash.bashrc already sets the default PS1.
# PS1='\h:\w\$ '
if [ -f /etc/bash.bashrc ]; then
. /etc/bash.bashrc
fi
else
if [ "id -u" -eq 0 ]; then
PS1='# '
else
PS1='$ '
fi
fi
fi

Nézzük meg a PS1 környezeti változó beállítását, ami nem más, mint a prompt jel. 🙂

Értelmezés: ha a PS1 környezeti változó beállított azaz definiált (set -u parancccsal ekvivalens a szintaxis, a set-ről a későbbiekben lesz szó), továbbá a BASH környezeti változó is létezik és értéke nem /bin/sh, akkor végrehajtja a /etc/bash.bashrc file-ban foglaltakat (a . <script-név> ekvivalens a source <script-név> jelöléssel) Nézzük csak meg ezt a file-t! Csak a prompt-beállítás szempontjából fontos részeket idézem.

gvamosi@gergo1:~$ cat /etc/bash.bashrc
# If not running interactively, don't do anything
[ -z "$PS1" ] && return

# set variable identifying the chroot you work in (used in the prompt below)
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
debian_chroot=$(cat /etc/debian_chroot)
fi

# set a fancy prompt (non-color, overwrite the one in /etc/profile)
# but only if not SUDOing and have SUDO_PS1 set; then assume smart user.
if ! [ -n "${SUDO_USER}" -a -n "${SUDO_PS1}" ]; then
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi

Ez a szkript-rész először megnézi, hogy nem zérus-e a PS1 környezeti változó, azután megpróbálja beállítani a debian_chroot változót – a chroot-ról majd később -, végül pedig beállítja a prompt-ot. Ha van chroot változó, akkor (ez_a_chroot) kezdetű, amúgy pedig \u – felhasználónév @ \h – hosztnév : \w munkakönyvtár és a végén egy dollárjel és egy “space” – üres karakter. 🙂

gvamosi@gergo1:~$

A ~ jel nem mást jelöl, mint a home könyvtárat. A pwd parancs mindig kiírja az aktuális könyvtárat.

gvamosi@gergo1:~$ pwd
/home/gvamosi

Az összes környezeti változót amúgy a set paranccsal kérdezhetjük le.

gvamosi@gergo1:~$ set | grep PS1
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '

A grep parancsról és a | pipe jelről pedig majd a későbbiekben írok. 🙂

A .bash_profile file a home könyvtárban és az alias-ok

Tartozom tegnapról egy magyarázattal. Volt ugye bár ez a parancs:

gvamosi@gergo1:/dev$ l tty3

Ez nem más, mint egy alias bejegyzés a home könyvtárban található .bash_profile-ból. Hogy mi ez a file? Amennyiben – egyébként szinte mindig – bash van beállítva a /etc/passwd file-ban login shell-nek – magyarázat egy későbbi postban 🙂 -, úgy az ebben a file-ban található parancsok belépéskor végre lesznek hajtva. No ide teszem vagy 20 éve a kedvenc alias-aimat. 🙂

gvamosi@gergo1:~$ cat .bash_profile

# added by gvamosi on 20170830
export PATH=$PATH:.
# added by gvamosi on 20170828
alias ls="ls --color"
alias l="ls -l"
alias la="ls -la"

Egyrészt beállítom keresési útvonalnak az aktuális könyvtárat az export paranccsal – ezek a tab billenyűvel elérhetőek, és az első pár karatkter begépelése jól jöhet 🙂 -, másrészt a kedvenc alias-aimat hozzáadom a shell-emhez. Ezek a színes file lista, és az l és la parancsok.

Még egy érdekesség a mai bejegyzés végére: a cd paranccsal – paraméter nélkül – a home könyvtárunkba kerülünk. 🙂

BASH programozás – script-ek

Beköszönés szintjén találtam egy rövidke ismertetőt a linux rendszerek parancssori programozásához. 🙂

http://web.cs.elte.hu/linfo/Shell/script.html

Az egyik script-et ki is próbáltam. Tényleg működik.

#!/bin/sh
for i in *.txt 
do
 if grep font $i > /dev/null
 then 
 mv $i ..
 fi
done

Hogy mit jelent az első sorban a /bin/sh? Kideríthetjük!

gvamosi@gergo1:~$ file /bin/sh
/bin/sh: symbolic link to dash
gvamosi@gergo1:~$ file /bin/dash
/bin/dash: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=486323dd0fe3ec5af388e4ea4217a1f0092961d2, stripped
gvamosi@gergo1:~$ file /bin/bash
/bin/bash: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=ffe165dc81a64aea2b05beda07aeda8ad71f1e7c, stripped
gvamosi@gergo1:~$ ls -l /bin/dash
-rwxr-xr-x 1 root root 121464 Jan 17 2019 /bin/dash
gvamosi@gergo1:~$ ls -l /bin/bash
-rwxr-xr-x 1 root root 1168776 Apr 18 06:12 /bin/bash

És hogy mit csinál a szkript? Megnézi a .txt kiterjestésű file-okat, hogy van-e bennük “font” sztring, és ekkor mozgatja őket a szülő “..” könyvtárba. 🙂