Wejście i wyjście standardowe oraz wyjście standardowe błędów
Procesy (uruchomione programy) w trybie tekstowym mają od początku działania
przyporządkowane trzy otwarte deskryptory:
- 0 - wejście standardowe (standard input, stdin)
- 1 - wyjście standardowe (standard output, stdout)
- 2 - standardowe wyjście błędów (standard error output, stderr)
Przez domniemanie wejście standardowe skojarzone jest z klawiaturą terminala, zaś wyjście
standardowe i standardowe wyjście błędów z oknem tekstowym terminala. Dlatego też
pojawiają się w nim zarówno użyteczne wyniki działania programów, jak i komunikaty o
błędach.
Przekierowania
Domniemane przyporządkowanie deskryptorów można zmienić (na przykład chcąc
wprowadzić z pliku dużą ilość danych lub zapisać w pliku dużą ilość wyników) przy użyciu
operatorów przekierowania:
program < plik
-wejście standardowe procesu zostanie skojarzone z danym plikiem (uwaga:
plik musi istnieć)
program > plik
-wyjście standardowe procesu zostanie skojarzone z danym plikiem. Jeżeli plik
nie istniał, będzie utworzony (jako pusty plik). Jeżli plik już istniał, jego dotychczasowa
zawartość zostanie usunięta (nadpisana)
program >> plik
-wyjście standardowe procesu zostanie skojarzone z danym plikiem. Jeśli plik
nie istniał, będzie utworzony (jako pusty plik). Jeśli plik już istniał, jego dotychczasowa
zawartość nie zostanie usunięta (proces będzie dopisywał do niej swoje wyniki)
program 2> plik
-standardowe wyjście błędów procesu zostanie skojarzone z danym plikiem.
Jeśli plik nie istniał, będzie utworzony (jako pusty plik). Jeśli plik już istniał, jego
dotychczasowa zawartość zostanie usunięta (nadpisana)
ZADANIA:
1. Przy użyciu polecenia
ls -l > plik
zapisać w pliku zawartość bieżącego katalogu (przekierować wyjście polecenia do pliku).
2. Napisać nieduży program w języku C zawierający kilka błędów składniowych,
skompilować go przy użyciu polecenia
gcc program.c
i obejrzeć wyświetlony wykaz
błędów. Użyć przekierowania standardowego wyjścia błędów:
gcc program.c 2> plik
, obejrzeć zawartość utworzonego pliku.
3. Utworzyć program w języku C:
#include <stdio.h>
int main(){
int n;
scanf("%d",&n);
printf("%d", n);
return 0;
}
Następnie uruchomić go i sprawdzić działanie.
3. Utworzyć kolejny program w języku C:
#include <stdio.h>
int main(int argc, char **argv){
printf("%s", argv[1]);
return 0;
}
Skompilować, a następnie uruchomić go poleceniem
./a.out 5
. Czym różnią się oba programy?
Język poleceń bash'a może być uważany za skryptowy język programowania.
Oznacza to, że polecenia
mogą nie tylko być używane w linii poleceń, ale również mogą być
umieszczane (w większej liczbie)
w plikach (nazywanych skryptami), które następnie są uruchamiane jako
całość. W związku z tym
skrypty muszą mieć nadane zarówno prawo do odczytu (r), jak i do
wykonywania (x) dla tego, kto je
będzie uruchamiał.
Języki skryptowe (interpretowane) różnią się od języków
kompilowanych tym, że programy w nich napisane nie podlegają kompilacji
(tłumaczeniu w całości i dołączaniu podprogramów bibliotecznych) na język
wewnętrzny komputera, tylko pojedyncze instrukcje podlegają tłumaczeniu "na
bieżąco" (są interpretowane przez program interpretera poleceń - w tym
przypadku przez bash'a). Niektóre języki programowania (na przykład Basic)
mogą być używane zarówno jako języki interpretowane, jak i kompilowane.
Programy skompilowane są wykonywane dużo szybciej, niż programy
interpretowane, ale wprowadzanie w nich zmian wymaga później ponownej
kompilacji całości.
W systemach uniksowych zazwyczaj jest dostępnych co najmniej kilka różnych
interpreterów, z których
jeden (zwykle bash) uważany jest za interpreter domyślny. W przypadku, gdy
skrypt przeznaczony jest
do wykonywania pod bieżącym interpreterem (tym, z którym aktualnie
współpracujemy w oknie
tekstowym), nie ma potrzeby umieszczania na jego początku żadnej dodatkowej
informacji, natomiast
jeśli chcemy wymusić interpretację skryptu przez pewien wybrany
interpreter, umieszczamy na jego
początku linię sterującą o postaci:
#!........ (bezwzględna ścieżka dostępu do programu interpretera)
Przykłady:
#!/bin/bash
#!/bin/csh
Innym sposobem jest podanie polecenia o postaci:
nazwa_interpretera nazwa_skryptu
Przykład:
sh moj_skrypt
Zad. 1
Utworzyć plik o dowolnej nazwie i następującej zawartości:
clear
echo "To jest pierwszy napis"
echo "A to jest drugi napis"
exit 0
Zad. 2Napisać i uruchomić skrypt wczytujący i wyświetlający łańcuch (napis):
clear
echo -n "Napisz cos: "
read x
echo "Otrzymalem napis: $x"
exit 0
Zad. 3Utworzyć skrypt, który w bieżącym katalogu tworzy podkatalog Teksty,
nastepnie towrzy pusty plik wiersz.txt i ustanawia prawa dostępu 755 do tego pliku. Na końcu wyświetla napis o zakończeniu działania.
Skrypty (podobnie, jak inne programy uruchamiane w trybie tekstowym) mogą w
chwili swojego
uruchomienia otrzymać pewną liczbę argumentów wywołania podanych w linii
poleceń:
nazwa_programu argument_1 argument_2 ... argument_n
Podawanie argumentów jest najbardziej podstawowym sposobem podawania danych
dla programu
(zwykle są to dane o charakterze "sterującym", a właściwy strumień danych
jest podawany przez
wejście standardowe). Programy mogą mieć stałą lub zmienną liczbę
argumentów.
UWAGA: sama nazwa programu też jest uważana za argument (o numerze 0).
Zad. 4Napisać i uruchomić skrypt, który:
a) otrzymuje trzy argumenty wywołania i kolejno je wyświetla:
echo $1 $2 $3
b) otrzymuje dowolną liczbę argumentów wywołania i wyświetla je
wszystkie:
echo $*
c) otrzymuje dowolną liczbę argumentów wywołania i wyświetla, ile ich
otrzymał:
echo $#
Zad. 5Utworzyć dwa proste skrypty o nazwach odpowiednio Pierwszy i Drugi,
które robią
cokolwiek (np. wyświetlają coś), a następnie skrypt, który po kolei
wywołuje je
w swojej treści (jako podprogramy):
...
echo Uruchamiam pierwszy skrypt
./Pierwszy
sleep 3
echo Uruchamiam drugi skrypt
./Drugi
sleep 3
echo Koncze dzialanie
exit 0