Дали некогаш сте морале да експериментирате со код или системски услужни програми во Linux за да не се грижите за основниот систем и да не уништите сè во случај на грешка во кодот што треба да работи со права на root?
Но, што е со фактот дека, да речеме, треба да тестирате или извршите цел кластер од различни микросервиси на една машина? Сто или дури илјада?
Со виртуелни машини управувани од хипервизор, ваквите проблеми можат и ќе се решат, но по која цена? На пример, контејнер во LXD базиран на дистрибуцијата на Alpine Linux троши само 7.60MB
RAM меморија, и каде root партицијата зафаќа по стартувањето 9.5MB
! Како ти се допаѓа тоа, Илон Маск? Препорачувам да се проверите основните можности на LXD - контејнерски систем во Linux
Откако стана јасно што се LXD контејнерите, ајде да одиме понатаму и да размислиме, што ако постоеше таква платформа за жетвар каде што можете безбедно да извршите код за домаќинот, да генерирате графикони, динамично (интерактивно) да ги поврзувате UI-виџетите со вашиот код, дополни го кодот со текст со блек џек... форматирање? Некој вид на интерактивен блог? Леле... сакам! Сака! 🙂
Погледнете под мачката каде што ќе лансираме во контејнер јупитер лабораторија - следната генерација на кориснички интерфејс наместо застарениот Jupyter Notebook, а ќе инсталираме и Python модули како на пр. Нуп, Панди, Матплотлиб, IPyWidgets што ќе ви овозможи да направите се што е наведено погоре и да го зачувате сето тоа во посебна датотека - лаптоп IPython.
Навигација
- План за орбитално полетување
- Инсталација и конфигурација на основниот систем
- Инсталирање на основен софтвер и поставување на системот
- Инсталирање и конфигурирање на JupyterLab
- Споделување податоци со домаќинот
- Здраво свету!
- Проширување на можностите на Python
- Тестирање на модули во JupyterLab
- Што друго?
План за орбитално полетување ^
Ајде да претставиме краток акционен план за да ни биде полесно да ја имплементираме шемата погоре:
- Ајде да инсталираме и лансираме контејнер врз основа на комплетот за дистрибуција Alpine Linux. Ќе ја користиме оваа дистрибуција бидејќи е насочена кон минимализам и во неа ќе го инсталираме само најпотребниот софтвер, ништо излишно.
- Ајде да додадеме дополнителен виртуелен диск во контејнерот и да му дадеме име -
hostfs
и монтирајте го во root датотечен систем. Овој диск ќе овозможи да се користат датотеки на домаќинот од даден директориум внатре во контејнерот. Така, нашите податоци ќе бидат независни од контејнерот. Ако контејнерот е избришан, податоците ќе останат на домаќинот. Исто така, оваа шема е корисна за споделување исти податоци помеѓу многу контејнери без користење на стандардните мрежни механизми на дистрибуцијата на контејнери. - Ајде да инсталираме Bash, sudo, потребните библиотеки, да додадеме и конфигурираме системски корисник
- Ајде да инсталираме Python, модули и да составиме бинарни зависности за нив
- Ајде да инсталираме и стартуваме јупитер лабораторија, прилагодете го изгледот, инсталирајте екстензии за него.
Во оваа статија ќе започнеме со лансирање на контејнерот, нема да размислуваме за инсталирање и конфигурирање на LXD, сето ова можете да го најдете во друга статија - Основни карактеристики на LXD - Linux контејнерските системи.
Инсталација и конфигурација на основниот систем ^
Создаваме контејнер со командата во која ја одредуваме сликата - alpine3
, идентификатор за контејнерот - jupyterlab
и, доколку е потребно, конфигурациски профили:
lxc init alpine3 jupyterlab --profile=default --profile=hddroot
Еве јас користам профил за конфигурација hddroot
кој одредува да се создаде контејнер со root партиција во Базен за складирање лоциран на физички HDD диск:
lxc profile show hddroot
config: {}
description: ""
devices:
root:
path: /
pool: hddpool
type: disk
name: hddroot
used_by: []
lxc storage show hddpool
config:
size: 10GB
source: /dev/loop1
volatile.initial_source: /dev/loop1
description: ""
name: hddpool
driver: btrfs
used_by:
- /1.0/images/ebd565585223487526ddb3607f5156e875c15a89e21b61ef004132196da6a0a3
- /1.0/profiles/hddroot
status: Created
locations:
- none
Ова ми дава можност да експериментирам со контејнери на HDD-дискот, заштедувајќи ги ресурсите на SSD-дискот, кој исто така е достапен во мојот систем 🙂 за што создадов посебен профил за конфигурација ssdroot
.
Откако ќе се создаде контејнерот, тој е во состојба STOPPED
, па затоа треба да го стартуваме со вклучување на системот иниција во него:
lxc start jupyterlab
Ајде да прикажеме листа на контејнери во LXD користејќи го клучот -c
што укажува на кој cприказ на колумните:
lxc list -c ns4b
+------------+---------+-------------------+--------------+
| NAME | STATE | IPV4 | STORAGE POOL |
+------------+---------+-------------------+--------------+
| jupyterlab | RUNNING | 10.0.5.198 (eth0) | hddpool |
+------------+---------+-------------------+--------------+
При креирањето на контејнерот, IP адресата беше избрана случајно, бидејќи користевме профил за конфигурација default
кој претходно беше конфигуриран во статијата Основни карактеристики на LXD - Linux контејнерските системи.
Ќе ја промениме оваа IP адреса во понезаборавна со создавање мрежен интерфејс на ниво на контејнер, а не на ниво на конфигурациски профил како што е сега во тековната конфигурација. Не мора да го правите ова, можете да го прескокнете.
Креирање мрежен интерфејс eth0
што го поврзуваме со прекинувачот (мрежен мост) lxdbr0
во кој го овозможивме NAT според претходната статија и контејнерот сега ќе има пристап до Интернет, а исто така доделуваме статичка IP адреса на интерфејсот - 10.0.5.5
:
lxc config device add jupyterlab eth0 nic name=eth0 nictype=bridged parent=lxdbr0 ipv4.address=10.0.5.5
По додавањето уред, контејнерот мора да се рестартира:
lxc restart jupyterlab
Проверка на статусот на контејнерот:
lxc list -c ns4b
+------------+---------+------------------+--------------+
| NAME | STATE | IPV4 | STORAGE POOL |
+------------+---------+------------------+--------------+
| jupyterlab | RUNNING | 10.0.5.5 (eth0) | hddpool |
+------------+---------+------------------+--------------+
Инсталирање на основен софтвер и поставување на системот ^
За да управувате со нашиот контејнер, треба да го инсталирате следниов софтвер:
пакет
Опис
баш
Школка GNU Bourne Again
баш-завршување
Програмабилно завршување за баш школка
sudo
Дајте им на одредени корисници можност да извршуваат некои команди како root
сенка
Пакет алатки за управување со лозинки и сметки со поддршка за датотеки во сенка и PAM
тздата
Извори за податоци за временската зона и летното сметање на времето
нано
Клонирање на уредувачот Пико со подобрувања
Дополнително, можете да инсталирате поддршка во системските man-pages со инсталирање на следните пакети − man man-pages mdocml-apropos less
lxc exec jupyterlab -- apk add bash bash-completion sudo shadow tzdata nano
Ајде да ги погледнеме командите и копчињата што ги користевме:
lxc
— Повикајте го клиентот LXDexec
- LXD клиент метод кој извршува команда во контејнеротjupyterlab
— ИД на контејнер--
- Посебен клуч кој одредува да не се толкуваат понатамошни клучеви како клучеви заlxc
и префрлете го остатокот од конецот како што е во садотapk
— Менаџер на пакети за дистрибуција на Alpine Linuxadd
— Метод за менаџер на пакети што ги инсталира пакетите наведени по командата
Следно, ќе поставиме временска зона во системот Europe/Moscow
:
lxc exec jupyterlab -- cp /usr/share/zoneinfo/Europe/Moscow /etc/localtime
По инсталирањето на временската зона, пакетот tzdata
повеќе не е потребен во системот, ќе заземе простор, па ајде да го избришеме:
lxc exec jupyterlab -- apk del tzdata
Проверка на временската зона:
lxc exec jupyterlab -- date
Wed Apr 15 10:49:56 MSK 2020
За да не трошиме многу време за поставување на Bash за нови корисници во контејнерот, во следните чекори ќе ги копираме готовите скел-датотеки од системот домаќин на него. Ова ќе ви овозможи интерактивно да го разубавите Bash во контејнер. Мојот систем за домаќин е Manjaro Linux и датотеките се копираат /etc/skel/.bash_profile
, /etc/skel/.bashrc
, /etc/skel/.dir_colors
во принцип тие се погодни за Alpine Linux и не предизвикуваат критични проблеми, но може да имате различна дистрибуција и треба самостојно да откриете дали има грешка при извршувањето на Bash во контејнерот.
Копирајте ги датотеките со скел во контејнерот. Клуч --create-dirs
ќе ги создаде потребните директориуми ако не постојат:
lxc file push /etc/skel/.bash_profile jupyterlab/etc/skel/.bash_profile --create-dirs
lxc file push /etc/skel/.bashrc jupyterlab/etc/skel/.bashrc
lxc file push /etc/skel/.dir_colors jupyterlab/etc/skel/.dir_colors
За постоечки root корисник, копирајте ги датотеките Skel штотуку копирани во контејнерот во домашниот директориум:
lxc exec jupyterlab -- cp /etc/skel/.bash_profile /root/.bash_profile
lxc exec jupyterlab -- cp /etc/skel/.bashrc /root/.bashrc
lxc exec jupyterlab -- cp /etc/skel/.dir_colors /root/.dir_colors
Alpine Linux инсталира системска школка за корисниците /bin/sh
, ќе го замениме со root
корисник во Bash:
lxc exec jupyterlab -- usermod --shell=/bin/bash root
Дека root
корисникот не бил без лозинка, тој треба да постави лозинка. Следната команда ќе генерира и постави нова случајна лозинка за него, која ќе ја видите на екранот на конзолата по нејзиното извршување:
lxc exec jupyterlab -- /bin/bash -c "PASSWD=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 12); echo "root:$PASSWD" | chpasswd && echo "New Password: $PASSWD""
New Password: sFiXEvBswuWA
Исто така, ајде да создадеме нов системски корисник - jupyter
за што подоцна ќе конфигурираме јупитер лабораторија:
lxc exec jupyterlab -- useradd --create-home --shell=/bin/bash jupyter
Ајде да генерираме и поставиме лозинка за тоа:
lxc exec jupyterlab -- /bin/bash -c "PASSWD=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 12); echo "jupyter:$PASSWD" | chpasswd && echo "New Password: $PASSWD""
New Password: ZIcbzWrF8tki
Следно, ќе извршиме две команди, првата ќе создаде системска група sudo
, а вториот ќе додаде корисник на него jupyter
:
lxc exec jupyterlab -- groupadd --system sudo
lxc exec jupyterlab -- groupmems --group sudo --add jupyter
Ајде да видиме во кои групи припаѓа корисникот jupyter
:
lxc exec jupyterlab -- id -Gn jupyter
jupyter sudo
Се е во ред, да продолжиме понатаму.
Дозволете ги сите корисници кои се членови на групата sudo
користете команда sudo
. За да го направите ова, извршете ја следнава скрипта, каде sed
ја декоментира параметарската линија во конфигурациската датотека /etc/sudoers
:
lxc exec jupyterlab -- /bin/bash -c "sed --in-place -e '/^#[ t]*%sudo[ t]*ALL=(ALL)[ t]*ALL$/ s/^[# ]*//' /etc/sudoers"
Инсталирање и конфигурирање на JupyterLab ^
јупитер лабораторија е апликација за Python, затоа прво мора да го инсталираме овој толкувач. Исто така, јупитер лабораторија ќе инсталираме користејќи го менаџерот на пакети Python pip
, а не системскиот, бидејќи можеби е застарен во системското складиште и затоа, мораме рачно да ги решиме зависностите за него со инсталирање на следните пакети − python3 python3-dev gcc libc-dev zeromq-dev
:
lxc exec jupyterlab -- apk add python3 python3-dev gcc libc-dev zeromq-dev
Ајде да ги ажурираме python модулите и менаџерот на пакети pip
до тековната верзија:
lxc exec jupyterlab -- python3 -m pip install --upgrade pip setuptools wheel
Намести јупитер лабораторија преку менаџер на пакети pip
:
lxc exec jupyterlab -- python3 -m pip install jupyterlab
Бидејќи проширувањата во јупитер лабораторија се експериментални и не се официјално испорачани со пакетот jupyterlab, затоа мораме рачно да го инсталираме и конфигурираме.
Ајде да инсталираме NodeJS и менаџерот на пакети за него - NPM, бидејќи јупитер лабораторија ги користи за своите екстензии:
lxc exec jupyterlab -- apk add nodejs npm
До екстензии за јупитер лабораторија кои ќе ги инсталираме работеа, тие треба да се инсталираат во корисничкиот директориум бидејќи апликацијата ќе биде лансирана од корисникот jupyter
. Проблемот е што нема параметар во командата за лансирање што може да се пренесе во директориумот; апликацијата прифаќа само променлива на околината и затоа мора да ја дефинираме. За да го направите ова, ќе ја напишеме командата за променлива извоз JUPYTERLAB_DIR
во околината на корисникот jupyter
, да поднесе .bashrc
што се извршува секогаш кога корисникот се најавува:
lxc exec jupyterlab -- su -l jupyter -c "echo -e "nexport JUPYTERLAB_DIR=$HOME/.local/share/jupyter/lab" >> .bashrc"
Следната команда ќе инсталира специјална екстензија - менаџер на екстензии во јупитер лабораторија:
lxc exec jupyterlab -- su -l jupyter -c "export JUPYTERLAB_DIR=$HOME/.local/share/jupyter/lab; jupyter labextension install --no-build @jupyter-widgets/jupyterlab-manager"
Сега сè е подготвено за првото лансирање јупитер лабораторија, но сепак можеме да инсталираме неколку корисни екстензии:
toc
— Содржина, генерира листа на наслови во статија/тетраткаjupyterlab-horizon-theme
- Тема на UIjupyterlab_neon_theme
- Тема на UIjupyterlab-ubu-theme
- Друг тема од авторот оваа статија :) Но, во овој случај, ќе се прикаже инсталацијата од складиштето GitHub
Значи, извршете ги следните команди последователно за да ги инсталирате овие екстензии:
lxc exec jupyterlab -- su -l jupyter -c "export JUPYTERLAB_DIR=$HOME/.local/share/jupyter/lab; jupyter labextension install --no-build @jupyterlab/toc @mohirio/jupyterlab-horizon-theme @yeebc/jupyterlab_neon_theme"
lxc exec jupyterlab -- su -l jupyter -c "wget -c https://github.com/microcoder/jupyterlab-ubu-theme/archive/master.zip"
lxc exec jupyterlab -- su -l jupyter -c "unzip -q master.zip && rm master.zip"
lxc exec jupyterlab -- su -l jupyter -c "export JUPYTERLAB_DIR=$HOME/.local/share/jupyter/lab; jupyter labextension install --no-build jupyterlab-ubu-theme-master"
lxc exec jupyterlab -- su -l jupyter -c "rm -r jupyterlab-ubu-theme-master"
По инсталирањето на екстензии, мора да ги составиме, бидејќи претходно, за време на инсталацијата, го наведовме клучот --no-build
да заштедите време. Сега значително ќе забрзаме со тоа што ќе ги составиме заедно во едно движење:
lxc exec jupyterlab -- su -l jupyter -c "export JUPYTERLAB_DIR=$HOME/.local/share/jupyter/lab; jupyter lab build"
Сега извршете ги следните две команди за да го извршите за прв пат јупитер лабораторија. Би можело да се активира со една команда, но во овој случај, командата за лансирање, која е тешко да се запомни во вашиот ум, ќе биде запаметена по баш во контејнерот, а не на домаќинот, каде што веќе има доволно команди. да ги запишам во историјата :)
Најавете се во контејнерот како корисник jupyter
:
lxc exec jupyterlab -- su -l jupyter
Следно, трчај јупитер лабораторија со копчиња и параметри како што е наведено:
[jupyter@jupyterlab ~]$ jupyter lab --ip=0.0.0.0 --no-browser
Одете на адресата во вашиот веб-прелистувач http://10.0.5.5:8888 и на страницата што се отвора внесете знак пристап кој ќе го видите во конзолата. Копирајте ја и залепете ја на страницата, а потоа кликнете најави се. Откако ќе се најавите, одете во менито со екстензии лево, како што е прикажано на сликата подолу, каде што ќе ви биде побарано, при активирање на менаџерот за екстензии, да преземете безбедносни ризици со инсталирање на екстензии од трети страни за кои командата Развој на JupyterLab не е одговорен:
Сепак, ние го изолираме целиот јупитер лабораторија и ставете го во контејнер така што наставките од трети страни кои бараат и користат NodeJS не можат барем да украдат податоци на дискот, освен оние што ги отвораме во контејнерот. Дојдете до вашите приватни документи на домаќинот во /home
процесите од контејнерот веројатно нема да успеат, а ако успеат, тогаш треба да имате привилегии за датотеките на системот домаќин, бидејќи го работиме контејнерот во непривилегиран режим. Врз основа на овие информации, можете да го процените ризикот од вклучување на екстензии во јупитер лабораторија.
Создадени IPython тетратки (страници во јупитер лабораторија) сега ќе се креира во домашниот директориум на корисникот - /home/jupyter
, но нашите планови се да ги поделиме податоците (споделувањето) помеѓу домаќинот и контејнерот, затоа вратете се во конзолата и престанете јупитер лабораторија со извршување копче - CTRL+C
и одговарање y
по барање. Потоа прекинете ја интерактивната сесија на корисникот jupyter
завршување на копче CTRL+D
.
Споделување податоци со домаќинот ^
За да споделите податоци со домаќинот, треба да креирате уред во контејнерот што ви овозможува да го направите тоа и за да го направите ова, извршете ја следнава команда каде што ги специфицираме следните клучеви:
lxc config device add
— Командата ја додава конфигурацијата на уредотjupyter
— ID на контејнерот на кој е додадена конфигурацијатаhostfs
— ID на уред. Можете да поставите кое било име.disk
— Типот на уредот е означенpath
— Ја одредува патеката во контејнерот до која LXD ќе го монтира овој уредsource
— Наведете го изворот, патеката до директориумот на домаќинот што сакате да го споделите со контејнерот. Наведете ја патеката според вашите преференции
lxc config device add jupyterlab hostfs disk path=/mnt/hostfs source=/home/dv/projects/ipython-notebooks
За каталогот /home/dv/projects/ipython-notebooks
дозволата мора да биде поставена на корисникот на контејнерот кој моментално има UID еднаков на SubUID + UID
, види поглавје Безбедност. Привилегии за контејнери во статијата Основни карактеристики на LXD - Linux контејнерските системи.
Поставете ја дозволата за домаќинот, каде што сопственикот ќе биде корисникот на контејнерот jupyter
, и променливата $USER
ќе го наведе вашиот домаќин корисник како група:
sudo chown 1001000:$USER /home/dv/projects/ipython-notebooks
Здраво свету! ^
Ако сè уште имате отворена сесија на конзола во контејнерот со јупитер лабораторија, потоа рестартирајте го со нов клуч --notebook-dir
со поставување на вредноста /mnt/hostfs
како патека до коренот на лаптопите во контејнерот за уредот што го создадовме во претходниот чекор:
jupyter lab --ip=0.0.0.0 --no-browser --notebook-dir=/mnt/hostfs
Потоа одете на страницата http://10.0.5.5:8888 и креирајте го вашиот прв лаптоп со кликнување на копчето на страницата како што е прикажано на сликата подолу:
Потоа, во полето на страницата, внесете го кодот на Python што ќе го прикаже класикот Hello World!
. Кога ќе завршите со внесување, притиснете CTRL+ENTER
или копчето „play“ на лентата со алатки на врвот за да може JupyterLab да го направи ова:
Во овој момент, речиси сè е подготвено за употреба, но ќе биде неинтересно ако не инсталираме дополнителни Python модули (целосни апликации) кои можат значително да ги прошират стандардните можности на Python во јупитер лабораторијазатоа, да продолжиме понатаму :)
PS Интересно е што старата имплементација Јупитер под кодно име Upупитер тетратка не исчезна и постои паралелно со јупитер лабораторија. За да се префрлите на старата верзија, следете ја врската со додавање на наставката во адресата/tree
, а преминот кон новата верзија се врши со наставката /lab
, но не мора да се специфицира:
- тетратка Јупитер - http://10.0.5.5:8888/tree
- Лабораторија Јупитер - http://10.0.5.5:8888/lab
Проширување на можностите на Python ^
Во овој дел, ќе инсталираме такви моќни јазични модули на Python како Нуп, Панди, Матплотлиб, IPyWidgets чии резултати се интегрирани во лаптопите јупитер лабораторија.
Пред да ги инсталирате наведените Python модули преку менаџерот на пакети pip
прво мора да ги решиме системските зависности во Alpine Linux:
g++
— Потребни за компајлирање модули, бидејќи некои од нив се имплементирани на јазикот C + + и поврзете се со Python при извршување како бинарни модулиfreetype-dev
- зависност за модулот Python Матплотлиб
Инсталирање на зависности:
lxc exec jupyterlab -- apk add g++ freetype-dev
Има еден проблем: во моменталната состојба на дистрибуцијата на Alpine Linux, нема да биде можно да се компајлира новата верзија на NumPy; ќе се појави грешка во компилацијата што не можев да ја решам:
ГРЕШКА: Не може да се изградат тркала за numpy кои користат PEP 517 и не можат директно да се инсталираат
Затоа, ќе го инсталираме овој модул како системски пакет кој дистрибуира веќе компајлирана верзија, но малку постара од она што е моментално достапно на страницата:
lxc exec jupyterlab -- apk add py3-numpy py3-numpy-dev
Следно, инсталирајте ги модулите на Python преку менаџерот на пакети pip
. Ве молиме бидете трпеливи бидејќи некои модули ќе се состават и може да потрае неколку минути. На мојата машина, компилацијата траеше ~ 15 минути:
lxc exec jupyterlab -- python3 -m pip install pandas ipywidgets matplotlib
Чистење на кешот за инсталација:
lxc exec jupyterlab -- rm -rf /home/*/.cache/pip/*
lxc exec jupyterlab -- rm -rf /root/.cache/pip/*
Тестирање на модули во JupyterLab ^
Ако трчате јупитер лабораторија, рестартирајте го за да се активираат новоинсталираните модули. За да го направите ова, во сесијата на конзолата, кликнете CTRL+C
каде што го имате да работи и влезете y
да го прекинете барањето и потоа да започнете повторно јупитер лабораторија со притискање на стрелката нагоре на тастатурата за да не се внесе наредбата повторно и потоа Enter
за да го започнете:
jupyter lab --ip=0.0.0.0 --no-browser --notebook-dir=/mnt/hostfs
Одете на страницата http://10.0.5.5:8888/lab или освежете ја страницата во вашиот прелистувач, а потоа внесете го следниов код во нова ќелија на тетратка:
%matplotlib inline
from ipywidgets import interactive
import matplotlib.pyplot as plt
import numpy as np
def f(m, b):
plt.figure(2)
x = np.linspace(-10, 10, num=1000)
plt.plot(x, m * x + b)
plt.ylim(-5, 5)
plt.show()
interactive_plot = interactive(f, m=(-2.0, 2.0), b=(-3, 3, 0.5))
output = interactive_plot.children[-1]
output.layout.height = '350px'
interactive_plot
Треба да добиете резултат како на сликата подолу, каде IPyWidgets генерира UI елемент на страницата што интерактивно комуницира со изворниот код, а исто така Матплотлиб го прикажува резултатот од кодот во форма на слика како функционален график:
Многу примери IPyWidgets можете да го најдете во упатствата тука
Што друго? ^
Браво ако останавте и стигнавте до самиот крај на статијата. Јас намерно не објавив готова скрипта на крајот од статијата што ќе се инсталира јупитер лабораторија со „еден клик“ за да ги поттикнете работниците :) Но, можете сами да го направите тоа, бидејќи веќе знаете како, откако ги собравте командите во една скрипта на Bash :)
Можете исто така да:
- Поставете име на мрежа за контејнерот наместо IP адреса со тоа што ќе го напишете на едноставен начин
/etc/hosts
и напишете ја адресата во прелистувачот http://jupyter.local:8888 - Играјте околу ограничувањето на ресурсите за контејнерот, за ова прочитајте го поглавјето основни LXD способности или добијте повеќе информации на страницата за програмери на LXD.
- Променете ја темата:
И многу повеќе што можете да направите! Тоа е се. Ти посакувам успех!
АЖУРИРАЊЕ: 15.04.2020 18:30 часот - Поправени грешки во поглавјето „Здраво, свето!“
АЖУРИРАЊЕ: 16.04.2020 10:00 — Поправен и додаден текст во описот на активирањето на менаџерот за екстензии јупитер лабораторија
АЖУРИРАЊЕ: 16.04.2020 10:40 — Поправени грешки пронајдени во текстот и малку изменети на подобро поглавјето „Инсталирање основен софтвер и поставување на системот“
Извор: www.habr.com