Historia Programowania i Języków Skryptowych
1/50

Wprowadzenie do Historii Programowania

Szanowni Państwo, witam na wykładzie poświęconym fascynującej ewolucji myśli programistycznej. Nasza podróż rozpocznie się w czasach, gdy komputery były mechanicznymi marzeniami, a "programowanie" oznaczało fizyczną rekonfigurację maszyny. Prześledzimy, jak od prostych, mechanicznych kalkulatorów doszliśmy do maszyn o architekturze von Neumanna, które zrewolucjonizowały przetwarzanie danych. Zobaczymy, jak narodziła się potrzeba abstrakcji, prowadząc do powstania pierwszych języków niskiego poziomu, takich jak asembler. Ta część wykładu skupi się na fundamentalnych koncepcjach, które stały się kamieniem węgielnym dla całej informatyki. Zrozumienie tych początków jest kluczowe, aby w pełni docenić złożoność i elegancję współczesnych paradygmatów programowania, w tym języków skryptowych, które będą głównym tematem naszych dalszych rozważań.

    +---------------------------+
    |      WITAJ NA WYKŁADZIE   |
    +---------------------------+
    |                           |
    |   Historia Programowania  |
    |            i              |
    |  Języków Skryptowych      |
    |                           |
    |   Od Babbage'a do Basha   |
    |                           |
    +---------------------------+
                
Era Przedkomputerowa: Mechaniczne Początki
2/50

Mechaniczne Kalkulatory i Maszyny Analityczne

Zanim pojawiły się komputery elektroniczne, idea automatyzacji obliczeń zaprzątała umysły najwybitniejszych myślicieli. Już w XVII wieku Blaise Pascal stworzył Pascalinę, mechaniczną maszynę zdolną do dodawania i odejmowania. Jednak prawdziwy przełom koncepcyjny nastąpił w XIX wieku za sprawą Charlesa Babbage'a. Jego maszyna różnicowa, a zwłaszcza projekt maszyny analitycznej, stanowiły fundamenty współczesnej informatyki. Maszyna Analityczna miała posiadać jednostkę arytmetyczno-logiczną ("młyn") oraz pamięć ("magazyn"), a jej działanie miało być sterowane za pomocą kart perforowanych. Była to pierwsza w historii koncepcja programowalnego komputera ogólnego przeznaczenia, zdolnego do wykonywania dowolnych, zdefiniowanych przez użytkownika obliczeń. Chociaż nigdy nie została w pełni zbudowana za życia Babbage'a, jej architektura stanowiła inspirację dla pokoleń.

 +--------------------------+
 |  Maszyna Analityczna     |
 |    (Koncepcja Babbage'a) |
 +--------------------------+
 |                          |
 |  +-------------------+   |
 |  |   Karty Wejściowe |   |
 |  |   (Instrukcje)    |   |
 |  +-------------------+   |
 |           |              |
 |           v              |
 |  +-------------------+   |
 |  |     "Młyn"        |   |
 |  | (Jednostka CPU)   |   |
 |  +--------+----------+   |
 |           ^              |
 |           |              |
 |  +--------v----------+   |
 |  |    "Magazyn"      |   |
 |  |     (Pamięć)      |   |
 |  +-------------------+   |
 |                          |
 +--------------------------+
                
Pierwsza Programistka: Ada Lovelace
3/50

Wizja Ady Lovelace

Augusta Ada King, hrabina Lovelace, była bliską współpracowniczką Charlesa Babbage'a. Analizując projekt Maszyny Analitycznej, wykazała się niezwykłą przenikliwością, która wyprzedzała jej epokę o całe stulecie. W swoich notatkach do tłumaczenia artykułu na temat maszyny, zawarła nie tylko szczegółowy opis jej działania, ale również algorytm do obliczania liczb Bernoulliego. Algorytm ten jest dziś uznawany za pierwszy w historii program komputerowy. Co ważniejsze, Ada Lovelace dostrzegła potencjał maszyny wykraczający poza czyste obliczenia numeryczne. Sugerowała, że urządzenie mogłoby operować na dowolnych symbolach, a nie tylko liczbach, co otwierałoby drogę do tworzenia muzyki czy grafiki. Jej wizja komputera jako uniwersalnego narzędzia do manipulacji symbolami stanowiła proroczą zapowiedź rewolucji cyfrowej.

  ,d88b.d88b,
  88888888888
  `Y8888888Y'
    `Y888Y'
      `Y'
 Ada Lovelace (1815-1852)

 "Maszyna Analityczna tka
 wzory algebraiczne, tak jak
 krosno Jacquarda tka
 kwiaty i liście."
                
Maszyny o Stałym Przeznaczeniu: Era Okablowania
4/50

ENIAC i "Programowanie" przez Rekonfigurację

Pierwsze komputery elektroniczne, takie jak brytyjski Colossus czy amerykański ENIAC (Electronic Numerical Integrator and Computer), były gigantycznymi maszynami o stałym, choć rekonfigurowalnym, przeznaczeniu. Nie posiadały one programu przechowywanego w pamięci w dzisiejszym rozumieniu. Zmiana zadania obliczeniowego wymagała fizycznej interwencji inżynierów. "Programowanie" ENIAC-a polegało na żmudnym, wielogodzinnym lub nawet wielodniowym procesie ręcznego łączenia setek kabli na panelach krosowniczych oraz ustawianiu tysięcy przełączników. Każda taka konfiguracja tworzyła dedykowany obwód elektroniczny do rozwiązania konkretnego problemu, na przykład obliczenia trajektorii balistycznej. Był to proces niezwykle powolny, podatny na błędy i wymagający dogłębnej znajomości architektury maszyny. Brakowało fundamentalnej koncepcji, która oddzieliłaby program (software) od maszyny (hardware).

Panel Krosowniczy ENIAC (Uproszczony Schemat)

+---------------------------------------------+
|                                             |
|  [Moduł A]      [Moduł B]      [Moduł C]    |
|  o-o-o-o        o-o-o-o        o-o-o-o      |
|  | | | |        | | | |        | | | |      |
|  o-o-o-o        o-o-o-o        o-o-o-o      |
|    |   \__________/   |          |          |
|    \------------------/          |          |
|        |                         |          |
|  [Moduł D]      [Moduł E]      [Moduł F]    |
|  o-o-o-o        o-o-o-o        o-o-o-o      |
|  | | | |        | | | |        | | | |      |
|  o-o-o-o        o-o-o-o        o-o-o-o      |
|                                             |
+---------------------------------------------+
   "Programowanie" = Ręczne łączenie modułów kablami
                
Rewolucja Koncepcyjna: Architektura von Neumanna
5/50

Koncepcja Programu Przechowywanego w Pamięci

W 1945 roku matematyk John von Neumann, w raporcie "First Draft of a Report on the EDVAC", sformalizował ideę, która na zawsze zmieniła oblicze informatyki. Zaproponował on architekturę komputera, w której zarówno instrukcje programu, jak i dane, na których operuje, są przechowywane w tej samej, wspólnej pamięci. Ta z pozoru prosta koncepcja była rewolucyjna. Oznaczała, że programy można traktować jak dane – można je wczytywać, modyfikować i zapisywać bez fizycznej ingerencji w sprzęt. Komputer stawał się maszyną uniwersalną, której funkcjonalność zależała wyłącznie od załadowanego do pamięci programu. Architektura ta, składająca się z jednostki arytmetyczno-logicznej (ALU), jednostki sterującej, pamięci oraz urządzeń wejścia-wyjścia, do dziś stanowi podstawę budowy niemal wszystkich komputerów na świecie.

+---------------------------------+
|      Architektura von Neumanna  |
+---------------------------------+
|                                 |
|      +-------------------+      |
|      | Jednostka         |      |
|      | Sterująca (CU)    |      |
|      +--------+----------+      |
|               ^                 |
|               |                 |
|      +--------v----------+      |
|      | ALU               |<---->|
|      +-------------------+      |
|               ^                 |
|               |                 |
|      +--------v----------+      |
|      | Pamięć            |      |
|      |(Dane i Instrukcje)|      |
|      +-------------------+      |
|          ^         ^            |
|          |         |            |
|      Wejście     Wyjście        |
+---------------------------------+
                
Pierwsze Komputery z Programem w Pamięci
6/50

Od Teorii do Praktyki: Manchester Baby i EDSAC

Koncepcja von Neumanna szybko znalazła swoje odzwierciedlenie w praktyce. Pierwszym na świecie komputerem, który uruchomił program przechowywany w pamięci, był Manchester Baby (Small-Scale Experimental Machine) w czerwcu 1948 roku. Jego program, mający na celu znalezienie największego dzielnika liczby, był niezwykle prosty, ale jego pomyślne wykonanie stanowiło dowód słuszności nowej architektury. Niedługo później, w 1949 roku, na Uniwersytecie w Cambridge uruchomiono komputer EDSAC (Electronic Delay Storage Automatic Calculator). Był to pierwszy w pełni funkcjonalny i praktycznie użyteczny komputer oparty na architekturze von Neumanna. Posiadał już zaczątki systemu operacyjnego w postaci procedur startowych wczytujących programy z taśmy perforowanej. To właśnie na EDSAC narodziła się idea bibliotek podprogramów, które można było wielokrotnie wykorzystywać w różnych programach.

     1948 - Manchester Baby                 1949 - EDSAC
+-------------------------+      +-------------------------------+
| Uruchomienie pierwszego |      | Pierwszy praktycznie użyteczny|
| programu z pamięci      |      | komputer z programem w pamięci|
|                         |      |                               |
| Pamięć: 32 słowa 32-bit |      | Pamięć: 1024 słowa 17-bitowe  |
|                         |      |                               |
| Cel: Dowód koncepcji    |      | Cel: Narzędzie badawcze       |
+-------------------------+      +-------------------------------+
             |                                  |
             +----------------------------------+
                             |
                             v
           +-------------------------------------+
           | Kamienie milowe w realizacji        |
           | architektury von Neumanna           |
           +-------------------------------------+
                
Podsumowanie Ery Pionierskiej
7/50

Od Mechaniki do Programu w Pamięci

Okres, który właśnie omówiliśmy, stanowi fundament całej rewolucji cyfrowej. Zaczęliśmy od mechanicznych wizji Babbage'a i profetycznych notatek Ady Lovelace, które po raz pierwszy zdefiniowały pojęcie programowalnej maszyny. Następnie byliśmy świadkami ery "twardego" programowania, gdzie zmiana zadania komputera, takiego jak ENIAC, wymagała fizycznej rekonfiguracji połączeń kablowych. Był to okres, w którym oprogramowanie i sprzęt stanowiły nierozerwalną całość. Prawdziwym przełomem okazała się architektura von Neumanna, która wprowadziła rewolucyjną koncepcję przechowywania programu i danych w tej samej pamięci. Komputery takie jak Manchester Baby i EDSAC udowodniły, że ta idea jest nie tylko możliwa, ale również niezwykle praktyczna. To właśnie ten moment oddzielił software od hardware'u, otwierając drogę do rozwoju języków programowania.

Ewolucja Koncepcji Programowania

1. Maszyna Analityczna (idea)
   [Program na kartach perfor.]

           |
           v

2. ENIAC (sprzęt)
   [Program = okablowanie]
   +-----------+
   |           |
   | Hardware  |
   | +Software |
   |           |
   +-----------+

           |
           v

3. EDSAC (arch. von Neumanna)
   [Program w pamięci]
   +----------+   +----------+
   | Hardware |   | Software |
   +----------+   +----------+
                
Narodziny Języków Niskiego Poziomu
8/50

Potrzeba Abstrakcji: Języki Niskiego Poziomu

Wraz z pojawieniem się komputerów z programem w pamięci, programiści stanęli przed nowym wyzwaniem. Programowanie polegało na bezpośrednim wprowadzaniu do pamięci maszyny sekwencji zer i jedynek, czyli kodu maszynowego. Był to proces niezwykle żmudny, podatny na błędy i całkowicie niezrozumiały dla człowieka nieposiadającego dogłębnej wiedzy o architekturze danego procesora. Każda, nawet najmniejsza zmiana w programie, wymagała ręcznego przeliczania adresów i instrukcji. Stało się jasne, że potrzebny jest wyższy poziom abstrakcji, który pozwoliłby programistom wyrażać swoje intencje w bardziej przystępny sposób, jednocześnie zachowując ścisłą kontrolę nad działaniem sprzętu. Odpowiedzią na tę potrzebę było stworzenie języków niskiego poziomu, które stanowiły cienką warstwę symboliczną nad surowym kodem maszynowym.

Problem:
+------------------------------------+
| Programista vs. Kod maszynowy      |
+------------------------------------+
|                                    |
| Człowiek     <------>     Maszyna  |
| (logika)     (nieczytelny) (bity)  |
|                                    |
|   10110010 00010110                |
|   10001001 11011000                |
|   01010010                         |
|   ...                              |
|                                    |
|   Potrzeba: Język pośredni!        |
+------------------------------------+
                
Kod Maszynowy: Język Procesora
9/50

Bezpośrednia Komunikacja ze Sprzętem

Kod maszynowy jest jedynym językiem, który procesor komputera (CPU) jest w stanie bezpośrednio zrozumieć i wykonać. Składa się on z sekwencji binarnych instrukcji (rozkazów), które sterują podstawowymi operacjami procesora, takimi jak operacje arytmetyczne, logiczne, transfer danych między rejestrami a pamięcią czy sterowanie przepływem programu. Każdy typ procesora posiada swój własny, unikalny zestaw instrukcji (Instruction Set Architecture, ISA). Oznacza to, że program napisany w kodzie maszynowym dla jednego procesora nie będzie działał na innym. Programowanie w kodzie maszynowym wymagało od programisty nie tylko perfekcyjnej znajomości ISA, ale również ręcznego zarządzania każdym bitem informacji, każdym adresem w pamięci i każdym rejestrem procesora. Była to praca niezwykle precyzyjna, ale jednocześnie bardzo nieefektywna i obarczona ogromnym ryzykiem błędu.

// Przykład (hipotetyczny) kodu maszynowego
// Zadanie: Dodaj wartość 5 do rejestru R1

10110001 // Instrukcja: Załaduj wartość do R1
00000101 // Wartość: 5

10110010 // Instrukcja: Załaduj wartość do R2
00000111 // Wartość: 7

00000011 // Instrukcja: Dodaj R2 do R1
11001010 // Kod operacji dla R1 i R2
                
Język Asemblera: Pierwszy Poziom Abstrakcji
10/50

Mnemoniki w Służbie Programisty

Aby uwolnić programistów od konieczności zapamiętywania binarnych kodów operacji, stworzono język asemblera. Stanowi on symboliczną reprezentację kodu maszynowego, gdzie każdej binarnej instrukcji przypisany jest łatwiejszy do zapamiętania mnemonik (np. `MOV` od "move", `ADD` od "add", `JMP` od "jump"). Zamiast operować na surowych adresach pamięci, asembler pozwalał na używanie etykiet symbolicznych do oznaczania fragmentów kodu lub danych. To znacznie upraszczało pisanie i modyfikowanie programów, zwłaszcza w kontekście skoków i wywołań podprogramów. Mimo że asembler nadal utrzymuje relację jeden do jednego z kodem maszynowym i jest ściśle związany z architekturą konkretnego procesora, stanowił on gigantyczny krok naprzód w dziedzinie czytelności i efektywności programowania.

// To samo zadanie w asemblerze
MOV R1, #5   // Przenieś wartość 5 do rejestru R1
MOV R2, #7   // Przenieś wartość 7 do rejestru R2
ADD R1, R1, R2 // Dodaj R2 do R1, wynik w R1
                
Rola Asemblera: Tłumacz Symboli
11/50

Automatyzacja Tłumaczenia na Kod Maszynowy

Kod napisany w języku asemblera nie jest bezpośrednio zrozumiały dla procesora. Potrzebny jest specjalny program, zwany asemblerem, który dokonuje jego translacji. Asembler czyta plik źródłowy z kodem symbolicznym i tłumaczy każdą instrukcję (mnemonik) na odpowiadający jej kod operacji w języku maszynowym. Przelicza także wszystkie etykiety na konkretne adresy w pamięci, rozwiązując problem ręcznego zarządzania adresacją. Proces ten, zwany asemblacją, jest znacznie prostszy i szybszy niż kompilacja języków wysokiego poziomu, ponieważ zachowuje bezpośrednią odpowiedniość między kodem źródłowym a wynikowym. Asembler był jednym z pierwszych i najważniejszych narzędzi programistycznych, które zautomatyzowało najbardziej żmudne i podatne na błędy aspekty programowania w kodzie maszynowym, pozwalając programistom skupić się bardziej na logice algorytmu.

		
		
Proces Asemblacji +-----------------------+ +---------------------+ +-----------------------+ | Plik źródłowy | | | | Plik wykonywalny | | (np. program.asm) | | ASEMBLER | | (kod maszynowy) | | |----->| (Tłumaczy mnemoniki |----->| | | MOV R1, #5 | | i etykiety na kod | | 10110001 00000101 | | ADD R1, R2 | | binarny) | | 00000011 11001010 | +-----------------------+ +---------------------+ +-----------------------+
Ograniczenia Języków Niskiego Poziomu
12/50

Brak Przenośności i Wysoka Złożoność

Mimo że asembler stanowił znaczące ułatwienie, wciąż posiadał fundamentalne ograniczenia. Najważniejszym z nich był całkowity brak przenośności. Program napisany w asemblerze dla procesora firmy Intel był bezużyteczny na maszynie z procesorem Motorola, ponieważ każdy z nich miał inną architekturę i zestaw instrukcji. Każda nowa platforma sprzętowa wymagała pisania oprogramowania od zera. Ponadto, tworzenie złożonych aplikacji w asemblerze było niezwykle trudne. Programista musiał samodzielnie zarządzać każdym aspektem działania programu, co prowadziło do długich, skomplikowanych i trudnych w utrzymaniu kodów. Brakowało w nim konstrukcji wyższego rzędu, takich jak pętle, instrukcje warunkowe czy złożone typy danych, które są standardem we współczesnym programowaniu. Potrzeba dalszej abstrakcji i uniezależnienia się od sprzętu stawała się coraz bardziej paląca.

+-------------------------+
| Problem:                |
| Brak Przenośności       |
+-------------------------+

+-------------------------+
| Program.asm dla x86     |
+-------------------------+
          |
          v
+-------------------------+
| Procesor Intel (x86)    | -- OK
+-------------------------+
          |
          v
+-------------------------+
| Procesor ARM            | -- BŁĄD!
+-------------------------+

Każda architektura wymagała
oddzielnego kodu.
                
Problem Efektywności i Przetwarzanie Wsadowe
13/50

Wykorzystanie Czasu Drogocennych Maszyn

W latach 50. i 60. XX wieku komputery typu mainframe były niezwykle drogie, zajmowały całe pomieszczenia i stanowiły centralny, dzielony zasób w instytucjach badawczych i korporacjach. Jednocześnie interakcja z nimi była bardzo nieefektywna. Operator musiał ręcznie załadować program (np. z kart perforowanych), uruchomić go, poczekać na zakończenie, a następnie załadować kolejny. W międzyczasie, podczas operacji wejścia-wyjścia czy zmiany taśmy, procesor pozostawał bezczynny, marnując cenne cykle obliczeniowe. Ta niska utylizacja zasobów była ekonomicznie nieakceptowalna. Zrodziła się potrzeba zautomatyzowania procesu uruchamiania kolejnych zadań, tak aby zminimalizować czas bezczynności procesora. Rozwiązaniem tego problemu okazała się koncepcja przetwarzania wsadowego (batch processing), która zrewolucjonizowała sposób zarządzania pracą komputerów.

Problem: Niska utylizacja CPU

 Operator         CPU             Drukarka
|                |               |
| Ładuje Zadanie |---------------| Bezczynna
|                |               |
| Czeka...       | Oblicza...    | Bezczynna
|                |               |
|                | Kończy        | Bezczynna
|                |               |
|                | Bezczynny     | Drukuje...
|                |               |
| Ładuje kolejne | Bezczynny     | Bezczynna
|                |               |
+-------------------------------------------> Czas

Cel: Minimalizacja bezczynności CPU.
                
Idea Przetwarzania Wsadowego
14/50

Automatyzacja Kolejki Zadań

Przetwarzanie wsadowe polegało na zebraniu grupy zadań (jobs) w jedną "partię" (batch) i przekazaniu jej komputerowi do wykonania w sposób zautomatyzowany, bez interwencji operatora między poszczególnymi zadaniami. Każde zadanie składało się z programu, danych wejściowych oraz specjalnych instrukcji sterujących, zapisanych w języku Job Control Language (JCL). Te instrukcje informowały system operacyjny, jakie zasoby są potrzebne, jaki program należy uruchomić i gdzie skierować wyniki. System operacyjny, a konkretnie jego komponent zwany monitorem wsadowym, automatycznie wczytywał kolejne zadania z partii, alokował zasoby, uruchamiał je i po zakończeniu zwalniał zasoby, natychmiast przechodząc do następnego zadania. Dzięki temu procesor był niemal ciągle zajęty, co radykalnie zwiększyło przepustowość i efektywność wykorzystania drogiego sprzętu komputerowego.

+-------------------------+
|  Partia Zadań (Batch)   |
|  (np. na taśmie)        |
+-------------------------+
|  [Nagłówek Zadania 1]   |
|  [Dane dla Zadania 1]   |
|  [Program 1]            |
|  ---------------------  |
|  [Nagłówek Zadania 2]   |
|  [Dane dla Zadania 2]   |
|  [Program 2]            |
|  ---------------------  |
|  [Nagłówek Zadania 3]   |
|  ...                    |
+-------------------------+
          |
          v
+-------------------------+
|  System Operacyjny      |
|  (Monitor Wsadowy)      |
|  * Czyta zadanie        |
|  * Uruchamia            |
|  * Przechodzi do nast.  |
+-------------------------+
                
Jak Działało Przetwarzanie Wsadowe?
15/50

Rola Job Control Language (JCL)

Sercem systemów wsadowych był język sterowania zadaniami, taki jak JCL w systemach IBM. Nie był to język programowania w klasycznym sensie, lecz język deklaratywny służący do opisu zadań dla systemu operacyjnego. Programista, przygotowując swoje zadanie na kartach perforowanych, musiał dołączyć karty sterujące JCL. Definiowały one między innymi identyfikator użytkownika, limity czasu i pamięci, potrzebne urządzenia (np. napędy taśm, drukarki) oraz ścieżki do plików z danymi wejściowymi i wyjściowymi. Karta `EXEC` (execute) wskazywała, który program z biblioteki systemowej ma zostać uruchomiony. Dzięki JCL system operacyjny mógł w pełni zautomatyzować zarządzanie zasobami i przepływem pracy, eliminując potrzebę ciągłego nadzoru operatora. Był to wczesny, ale niezwykle ważny krok w kierunku automatyzacji zadań administracyjnych, co stanowiło preludium do idei skryptowania.

// Bardzo uproszczony przykład karty JCL
//JOB ACCOUNT=ITDEPT,USER=SMITH
// Ten komentarz opisuje zadanie.
// DD definiuje zbiór danych (Data Definition)
//INPUT DD DSN=PROJ.DATA.INPUT,DISP=SHR
//OUTPUT DD SYSOUT=A
// EXEC wskazuje program do wykonania
//STEP1 EXEC PGM=CALCULATE
                
Od przetwarzania wsadowego do wielozadaniowości
16/50

Ograniczenia Modelu Wsadowego i Potrzeba Interakcji

Przetwarzanie wsadowe, mimo swojej efektywności w utylizacji CPU, miało istotną wadę: całkowity brak interaktywności. Programista oddawał swoje zadanie do "okienka" i na wyniki musiał czekać godzinami, a czasem nawet dniami. Cykl "kodowanie - uruchomienie - debugowanie" był niezwykle długi i frustrujący. Co więcej, nawet w systemie wsadowym procesor często był bezczynny, na przykład gdy program czekał na zakończenie wolnej operacji odczytu z taśmy magnetycznej. Zrodziła się więc koncepcja wielozadaniowości (multitasking) i systemów z podziałem czasu (time-sharing). Idea polegała na tym, aby w pamięci komputera znajdowało się jednocześnie wiele programów. Gdy jeden program czekał na operację wejścia/wyjścia, system operacyjny mógł przełączyć procesor na wykonywanie innego programu, maksymalizując wykorzystanie zasobów i dając złudzenie równoczesnego działania wielu zadań.

System z podziałem czasu

      +-----------+
      | Program A | ----> Czeka na I/O
      +-----------+
      +-----------+       +---------+
      | Program B | <---- |   CPU   |
      +-----------+       +---------+
      +-----------+           ^
      | Program C | ----------+
      +-----------+

System operacyjny szybko przełącza
CPU pomiędzy programami, które są
gotowe do wykonania.
                
Narodziny Interaktywnej Powłoki (Shell)
17/50

Bezpośredni Dialog z Maszyną

Systemy z podziałem czasu otworzyły drogę do nowego modelu interakcji: pracy terminalowej. Użytkownicy mogli łączyć się z centralnym komputerem za pomocą terminali i pracować z nim w trybie konwersacyjnym. Potrzebny był jednak program, który pełniłby rolę pośrednika między użytkownikiem a jądrem systemu operacyjnego – interpreter poleceń. Program ten, nazwany powłoką (shell), odczytywał polecenia wpisywane przez użytkownika, interpretował je i zlecał ich wykonanie systemowi operacyjnemu. Jednym z pierwszych i najbardziej wpływowych systemów, który spopularyzował tę ideę, był Multics, a następnie jego następca – UNIX. Powłoka systemowa nie tylko umożliwiała uruchamianie programów, ale także zarządzanie plikami, procesami i konfiguracją systemu. To właśnie w tym interaktywnym środowisku narodziła się idea skryptowania jako sposobu na automatyzację sekwencji poleceń.

Model Interaktywny

+------------+     +-----------------+     +-----------------+
| Użytkownik |<--->|     Terminal    |<--->|     Powłoka     |
+------------+     +-----------------+     |     (Shell)     |
                                           +--------+--------+
                                                   |
                                                   v
+------------------------------------------------------------------------+
|                          System Operacyjny (Jądro)                     |
|                                                                        |
| [Zarządzanie plikami]  [Zarządzanie procesami]  [Zarządzanie pamięcią] |
+------------------------------------------------------------------------+