[LPIC-1] Променливи, функции и акаунти.

Този урок покрива материала от LPIC-1 105.1, нужен за изпит 102-400.
Урока покрива следните команди и файлове:
1.
source
unset
export
2.
set
еnv

3.
/etc/bash.bashrc
/etc/profile
~/.bash_profile
~/.bash_login
~/.profile
~/.bashrc
~/.bash_logout
4.
function
alias

1. Еxport, source и unset

Стойността на дадена променлива в Линукс може да се провери чрез echo командата. Всички променливи започват със символът “$”. Следващия пример показва как да се провери съдържанието на променливата $BASHPID.

[boyan@localhost ~]$ echo $BASHPID
18609
[boyan@localhost ~]$ ps -e |fgrep bash
3154 pts/0 00:00:00 bash
3396 pts/1 00:00:02 bash
11890 pts/2 00:00:00 bash
18609 pts/3 00:00:00 bash

Ако отворим нов терминал чрез screen командата и наново извикаме echo $BASHPID ще видим че стойността му е друга.

[boyan@localhost ~]$ echo $BASHPID
18932
[boyan@localhost ~]$ ps -e |fgrep bash
3154 pts/0 00:00:00 bash
3396 pts/1 00:00:02 bash
11890 pts/2 00:00:00 bash
18609 pts/3 00:00:00 bash
18932 pts/4 00:00:00 bash

Това е така защото стойността на $BASHPID е id-то на shell-a върху който работим. Това ни довежда до едно от качествата на променливите, стойността им е такава каквато я зададем само за текущия ни shell. За да демонстрираме това първо ще трябва да си направим някаква променлива:

[boyan@localhost script]$ years=19
[boyan@localhost script]$ echo $years
19

Сега нека да направим някакъв скрипт който да използва тази променлива:

[boyan@localhost script]$ touch someScript
[boyan@localhost script]$ echo -e “#!/bin/bash \n echo I am $years old.” >> someScript
[boyan@localhost script]$ cat someScript
#!/bin/bash
echo I am $years old.

Правим го executable чрез chmod и го пускаме:

[boyan@localhost script]$ chmod + someScript
[boyan@localhost script]$ ./someScript
I am old.

И ни излиза че сме стари, което е невярно. Това съобщение излиза, не защото системата си мисли че сме стари, а защото променливата не е експортната(изкарана). Това означава, че тя е валидна само за нашия shell, а не за външни shell-ове. При пускането на скрипта чрез ./(име на скрипта) той се пуска в съб-shell, “дете” на нашия главен shell. Ако искаме да пуснем скрипта директно в нашия shell използваме source командата.

[boyan@localhost script]$ source someScript
I am 19 old.

Сега е момента да отбележим, че при извикването чрез source не е нужно да слагаме “./” пред името на скрипта. Друг начин за извикване на source командата е чрез “.”.

[boyan@localhost script]$ . someScript
I am 19 old.
[boyan@localhost script]$ . ./someScript
I am 19 old.

Макар и вече нашия скрипт да работи както трябва, той граматически не е правилен. Нужно е да променим съдържанието на нашата променлива, това става по следния начин:

[boyan@localhost script]$ years=”19 years”
[boyan@localhost script]$ . someScript
I am 19 years old.

При задаването на променлива, която ще съдържа празно място, се използват двойни кавички.Друг начин да направим това, което успяхме със source командата, е да използваме еxport.

[boyan@localhost script]$ currency=BTC
[boyan@localhost script]$ cat someOtherScript
#!/bin/bash
echo We accept $currency
[boyan@localhost script]$ chmod 777 someOtherScript
[boyan@localhost script]$ ./someOtherScript
We accept
[boyan@localhost script]$ export currency
[boyan@localhost script]$ ./someOtherScript
We accept BTC

Export командата ни прави променливата “глобална” в такъв смисъл че тя е валинда за нашите процеси “деца”.
Променлива може да се експортне още при самото и задаване. Следното е напълно валидна команда:

[boyan@localhost script]$ export ThisIs=OK

Извикана само по себе си “export” показва само променливите които са експортнати.

[boyan@localhost script]$ export ABC=CBA
[boyan@localhost script]$ export | head -n 5
declare -x ABC=”CBA”
declare -x HISTCONTROL=”ignoredups”
declare -x HISTSIZE=”1000″
declare -x HOME=”/home/boyan”
declare -x HOSTNAME=”localhost.localdomain”

Ако искаме да “изтрием” наша променлива трябва да използваме unset командата. Когато въвеждаме името на променливата то се въвежда без “$”.

[boyan@localhost script]$ unset years
[boyan@localhost script]$ . someScript
I am old.
[boyan@localhost script]$ unset currency
[boyan@localhost script]$ . someOtherScript
We accept

2. Set и env

Set командата сама по себе си извикана изкарва списък с всички променливи и функции в shell-a ни.

[boyan@localhost script]$ set | head
ABRT_DEBUG_LOG=/dev/null
BASH=/bin/bash
BASHOPTS=checkwinsize:cmdhist:expand_aliases:extglob:extquote:force_fignore:histappend:interactive_comments:progcomp:promptvars:sourcepath
BASHPID=18932
BASH_ALIASES=()
BASH_ARGC=()
BASH_ARGV=()
BASH_CMDS=()
BASH_COMPLETION_COMPAT_DIR=/etc/bash_completion.d
BASH_LINENO=()

Полезна опция на set е “set -о noclobber”, което забранява презаписването на файлове. При set командата “-о” се използва за включване на оции, а “+o” за изключване.

[boyan@localhost script]$ touch File
[boyan@localhost script]$ echo Hello > File
[boyan@localhost script]$ cat File
Hello
[boyan@localhost script]$ echo Hello Again > File
[boyan@localhost script]$ cat File
Hello Again
[boyan@localhost script]$ set -o noclobber
[boyan@localhost script]$ echo Hello > File
bash: File: cannot overwrite existing file
[boyan@localhost script]$ echo Hello >> File
[boyan@localhost script]$ cat File
Hello Again
Hello

Последното нещо за което може да се използва set се нарича позиционални параметри. Вътре във всеки shell има запазени имена за променливи, такива са $1 $2 ${10} и т.н.
Всичко неразпознато от set командата се задава към тези параметри.

[boyan@localhost script]$ set Tova Sa Pozicionalni Parametri
[boyan@localhost script]$ echo $1 $2 $3 $4 $5
Tova Sa Pozicionalni Parametri

При двуцифрените е нужно да се използват къдрави скоби {}.

[boyan@localhost script]$ set 1 2 3 4 5 6 7 8 9 10 11
[boyan@localhost script]$ echo $1 $5 ${10} ${11}
1 5 10 11

Командата env извикана сама по себе си показва всички променливи достъпни за sub-shells.

[boyan@localhost script]$ export | head -n 5
declare -x ABC=”CBA”
declare -x BTC
declare -x HISTCONTROL=”ignoredups”
declare -x HISTSIZE=”1000″
declare -x HOME=”/home/boyan”

Тя се използва за да пусне команда в модифицирана среда. Мястото ѝ е най-вече при “shebang” линията на някой скрипт(#!). Използвайки #!/bin/env ksh караме да нашия shell да търси за ksh в $PATH(в случай, че не знаем къде се намира).

3. Акаунти, $PATH, login и non-login shell-ове.

/etc/profile е скрипт, който се изпълнява за всички логин сесий, на потребители използващи bash shell-ът. След това се пускат(сорсват) файловете във /etc/profile.d.
Следващият файл, който се изпълнява, е ~/.bash_profile. Този скрипт съдържа частни настройки и променливи, които се отнасят само за дадения потребител. Ако ~/bash_profile не съществува се проверява за bash.login, а след това за .profile. Който и от трите скрипта да се изпълни се пренасочва след това към .bashrc. Последния скрипт, който се извършва е .bash_logout, който спира пуснатите процеси и изпълнява clear командата.

Примерен потребителски логин:

1.Потребителят въежда името и паролата си
2.Изпълнява се /etc/profile
3.Сорсват се файловете в /etc/profile.d
4.Изпълнява се ~/bash.profile
5.~/bash.profile пренасочва към .bashrc
6.Потребителят е свободен да извършва действия
7.За излизане се използва logout, exit или Ctrl+D
8.Изпълнява се .bash_logout

/etc/skel/ съдържа всички файлове които ще се прехвърлят към новосъздаден потребител. Така лесно може да задаваме насторйки за всички бъдещи потребители.

[boyan@localhost ~]$ cd /etc/skel/
[boyan@localhost skel]$ ls -a
. .. .bash_logout .bash_profile .bashrc .mozilla

Нека да проверим съдържането на ~/bash.profile. Файловете започващи с “.” са “скрити”,и не могат да се видят с обикновенна ls команда.

[boyan@localhost ~]$ ls
Arduino Documents Music Public Videos
Downloads VirtualBox VMs Desktop Pictures test

За да видим така наречените “скрити” файлове е нужно да използваме “-a” опцията на ls.

[boyan@localhost ~]$ ls -a | egrep ^[\\.]
.
..
.arduino15
.bash_history
.bash_logout
.bash_profile
.bashrc
.cache
.config
.esd_auth
.gimp-2.8
.gnome

Скрити файлове могат да бъдат всякакви файлове, например конфигурациите на определени програми и дори директории.

[boyan@localhost ~]$ cat .bash_profile
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi

# User specific environment and startup programs

PATH=$PATH:$HOME/.local/bin:$HOME/bin

export PATH

Както виждаме .bash_profile сорсва .bashrc, и задава стойността на променливата $PATH. $PATH показва къде да се търсят изпълняеми програми и в каква последователност.

[boyan@localhost ~]$ echo $PATH
/usr/lib64/qt-3.3/bin:/home/boyan/perl5/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/boyan/.local/bin:/home/boyan/bin:/home/boyan/.local/bin:/home/boyan/bin

Това ни позволява вместо да пишем цялата директория на дадена програма

[boyan@localhost ~]$ /usr/bin/xeyes

Да я отворим само чрез името на програмата

[boyan@localhost ~]$ xeyes

Затова и при пускането на скриптове които ги няма в $PATH е нужно ./имеНаСкрипт.
Ако създадем скрипт и го поставим в /usr/bin , ще може да го извикваме само чрез името му, без да посочваме пътя към него.

[boyan@localhost bin]$ cd /etc/bin | sudo touch dadada
[boyan@localhost bin]$ sudo vi dadada
[boyan@localhost bin]$ cat /usr/bin/dadada
#!/bin/bash
echo nenenne
[boyan@localhost bin]$ sudo chmod 777 dadada
[boyan@localhost bin]$ dadada ///намираме се в директорията на скрипта и го извикваме без ./
nenenne
[boyan@localhost bin]$ cd ~
[boyan@localhost ~]$ dadada ///не се намираме в директорията на скрипта и го извикваме без ./
nenenne

Добавянето на пътища към $PATH става чрез редактирането на .bash_profile и добавянето на пътя който искаме да добавим ( в този случай $HOME).
export PATH=$HOME/:$PATH
Това не не изтрива нищо от $PATH, а просто добавя $HOME към него.Можем и директно да го изпълним в командния ред, но ще е валидно само докато не излезем.

[boyan@localhost ~]$ PATH=$HOME/:$PATH
[boyan@localhost ~]$ echo $PATH
/home/boyan/:/usr/lib64/qt-3.3/bin:/home/boyan/perl5/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/boyan/.local/bin:/home/boyan/bin:/home/boyan/.local/bin:/home/boyan/bin

Non-login shell сесия е например: От root да използваме “su boyan” за временно преобразуване в друг профил. Така се изпълнява само и единствено ~/.bashrc. Ако искаме логин сесия, ще трябва да използваме “su boyan”.

4.Функции и alias.
Alias е съкратената версия на нещо. Един лесен пример е командата ll.

[boyan@localhost ~]$ cd /usr/local/
[boyan@localhost local]$ ll
total 40
drwxr-xr-x. 2 root root 4096 Nov 5 2016 bin
drwxr-xr-x. 2 root root 4096 Nov 5 2016 etc
drwxr-xr-x. 2 root root 4096 Nov 5 2016 games
drwxr-xr-x. 2 root root 4096 Nov 5 2016 include
drwxr-xr-x. 2 root root 4096 Nov 5 2016 lib
drwxr-xr-x. 2 root root 4096 Nov 5 2016 lib64
drwxr-xr-x. 2 root root 4096 Nov 5 2016 libexec
drwxr-xr-x. 2 root root 4096 Nov 5 2016 sbin
drwxr-xr-x. 5 root root 4096 Apr 8 23:09 share
drwxr-xr-x. 2 root root 4096 Nov 5 2016 src

ll всъщност изпълнява ls -l.Всички т.н съкращения могат да се проверят чрез въвеждането на alias командата.

[boyan@localhost local]$ alias
alias egrep=’egrep –color=auto’
alias fgrep=’fgrep –color=auto’
alias grep=’grep –color=auto’
alias l.=’ls -d .* –color=auto’
alias ll=’ls -l –color=auto’
alias ls=’ls –color=auto’
alias perlll=’eval `perl -Mlocal::lib`’
alias vi=’vim’
alias which=’alias | /usr/bin/which –tty-only –read-alias –show-dot –show-tilde’

Създаването на alias е лесна работа:

[boyan@localhost local]$ alias vkushti=”cd $HOME”
[boyan@localhost local]$ vkushti
[boyan@localhost ~]$ pwd
/home/boyan

Kакто и премахването му:

[boyan@localhost ~]$ unalias vkushti
[boyan@localhost ~]$ vkushti
bash: vkushti: command not found…

Функциите са подобни на алиасите, но изпълняват код вместо една команда.
Пример за функция:

[boyan@localhost dasolol]$ cat function
#!/bin/bash
print_something () {
pwd
}
echo Your directory is
print_something

[boyan@localhost dasolol]$ ./function
Your directory is
/home/boyan/test/tesT/dasolol
[boyan@localhost dasolol]$ pwd //доказателство че работи, като се изпълни pwd командата, която прави абсолютно същото нещо.
/home/boyan/test/tesT/dasolol

Пример за фукнция, която показва информация за системата и се изълнява при всеки login.

function yay() {
echo -e “\nMachine Info:”;uname -a
echo -e “\nLogged in users”; who
echo -e “\nUptime:”;uptime
echo -e “\nCPU:”;sensors| grep CPU
echo -e “\nMB:”;sensors| grep MB
echo -e “\nOther:”;sensors | grep -e Core -e temp1
}
yay

*Какво точно се показва строго зависи от системата, върху която се изпълнява*

Командата sensors идва от пакета lm_sensors.
За да се изпълни при всеки logim тя трябва да бъде поставена в /etc/profile.
След поставянето и там при login всеки потребител ще вижда нещо подобно:

Machine Info:
Linux boyan.website 4.4.0-116-generic #140-Ubuntu SMP Mon Feb 12 21:23:04 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

Logged in users
root tty1 2018-04-10 16:02
boyanweb pts/0 2018-05-03 21:41 (192.168.1.2)
boyanweb pts/8 2018-05-03 21:22 (192.168.1.3)

Uptime:
21:41:05 up 23 days, 5:39, 3 users, load average: 0.24, 0.22, 0.23

CPU:
CPU FAN Speed: 2596 RPM (min = 0 RPM, max = 7200 RPM)
CPU Temperature: +45.5°C (high = +60.0°C, crit = +95.0°C)

MB:
MB Temperature: +42.0°C (high = +45.0°C, crit = +95.0°C)

Other:
temp1: +78.0°C (high = +95.0°C, hyst = +3.0°C)
Core 0: +57.0°C (high = +78.0°C, crit = +100.0°C)
Core 1: +57.0°C (high = +78.0°C, crit = +100.0°C)

Ако искате само определени профили да виждат тази информация, то функцията може да се сложи и в ~/bash.rc или който и да е от другите файлове отговарящи за login процеса.

Автор:Боян Атанасов