Home

Linux

Cheatsheet

Find a file

By filename

find . -name *.cpp

By filename, ignore case

find . -iname *.cpp

Only folders

find . -type d -name *.cpp

Together with grep

find . -type f -exec grep "pattern" '{}' \; -print

This goes through every object in the current directory tree (.) that’s a file (-type f) and then runs grep ”pattern” for every file that matches, then prints them on the screen (-print). The curly braces ({}) are a placeholder for those results matched by the Linux find command. The {} go inside single quotes (‘) so that grep isn’t given a misshapen file name. The -exec command is ended with a semicolon (;), which also needs an escape (;) so that it doesn’t end up being interpreted by the shell.

Find string in a file

grep -rnw '.' -e 'pattern'

Filter files before

grep --include=\*.{cpp,hpp} -rnw '.' -e "pattern"

Check linkage between libraries

ldd <path_to_library_or_executable>
readelf -d <path_to_so_file>
objdump -p <path_to_so_file>

Server setup

Installation

SSH access

  • install SSH
sudo apt install openssh-server
sudo systemctl status ssh
sudo ufw allow ssh
  • add known public key
# cat ./.ssh/authorized_keys 
ssh-rsa AAAAB3NzaC1yc***************saH0M= zelva@notas-debian

.NET

Debian

wget https://packages.microsoft.com/config/debian/12/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
rm packages-microsoft-prod.deb

sudo apt-get update && sudo apt-get install -y dotnet-sdk-9.0

sudo apt-get update && sudo apt-get install -y aspnetcore-runtime-9.0

Ubuntu

  • install add-apt-repository
sudo apt update
sudo apt-get install software-properties-common
  • .NET repositories
sudo add-apt-repository ppa:dotnet/backports
  • install .NET SDK
sudo apt update
sudo apt-get install -y dotnet-sdk-9.0
sudo apt-get install -y aspnetcore-runtime-9.0
  • trust the development certificate
dotnet dev-certs https --trust

Update tools if needed

dotnet tool update --global dotnet-ef

New webapi project

dotnet new webapi -o projectapi
Packages
dotnet add package Microsoft.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.Tools

dotnet add package MySql.EntityFrameworkCore
dotnet add package MySql.Data

dotnet add package Microsoft.Extensions.Hosting
dotnet add package Microsoft.AspNetCore.HttpOverrides

dotnet add package Serilog.Extensions.Logging.File
dotnet add package SixLabors.ImageSharp
dotnet add package System.Net.Http.Json
Migrations
dotnet ef migrations add InitialCreate
dotnet ef migrations script > MigrationScripts/initial.sql

dotnet ef migrations add Products
dotnet ef migrations script previous_migration > MigrationScripts/products.sql

Supervisor

  • install
sudo apt install supervisor

Apache

  • install
sudo apt install apache2
  • setup firewall
sudo ufw app list
sudo ufw status
sudo ufw allow 'Apache'

sudo systemctl status apache2
  • enable localhost
sudo nano /etc/apache2/apache2.conf
add line after ServerRoot: ServerName localhost
  • restart
service apache2 restart
  • enable services
sudo a2enmod headers
a2enmod ssl
a2enmod rewrite
sudo a2enmod proxy_http
  • configure proxy
    • https://techexpert.tips/apache/enable-https-apache/
    • nano /etc/apache2/apache2.conf
    • add: AllowOverride All
    • add section
<Directory /var/www/>
	Options Indexes FollowSymLinks
	AllowOverride All
	Require all granted
</Directory>

Basic HTTP setup

<VirtualHost *:80>
  ServerAdmin admin@domain.cz
  ServerName domain.cz
  ServerAlias www.domain.cz
  DocumentRoot /var/www/domain.cz
  ErrorLog /var/www/domain.cz/domain-error.log
  CustomLog /var/www/domain.cz/domain-access.log combined
</VirtualHost>
  • enable site
a2ensite site_config

Let's Encrypt HTTPS certificate

  • install certbot
sudo apt-get install certbot
sudo apt-get install python3-certbot-apache 
  • get certificate
sudo certbot certonly --apache

HTTPS setup

<VirtualHost *:80>
  ServerName domain.cz
  ServerAlias www.domain.cz
  RewriteEngine On
  RewriteCond %{HTTPS} !=on 
  RewriteCond %{HTTP_HOST} ^(www\.)?(.*)$ [NC]
  RewriteRule ^ https://%2%{REQUEST_URI} [R=301,L]
</VirtualHost>
<VirtualHost *:443>
  ServerAdmin admin@domain.cz
  ServerName domain.cz
  ServerAlias www.domain.cz

  RewriteEngine On
  RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
  RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]
  DocumentRoot /var/www/domain.cz
  ErrorLog /var/www/domain.cz/domain-error.log
  CustomLog /var/www/domain.cz/domain-access.log combined
  SSLEngine on
  SSLCertificateFile /etc/letsencrypt/live/domain.cz/fullchain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/domain.cz/privkey.pem

  ProxyPreserveHost On
  ProxyVia on
  ProxyRequests Off
  <Location "/api/">
    ProxyPass http://127.0.0.1:5001/
    ProxyPassReverse http://127.0.0.1:5001/
  </Location>
</VirtualHost>

MySQL

  • install
wget -c https://dev.mysql.com/get/mysql-apt-config_0.8.33-1_all.deb
sudo dpkg -i mysql-apt-config_0.8.33-1_all.deb
sudo apt-get update
sudo apt-get install mysql-server
#remove anonymous user and test database
sudo mysql_secure_installation
sudo service mysql restart
sudo mysql -u root -p
  • configuration
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
  • database creation
CREATE DATABASE IF NOT EXISTS `db_name` DEFAULT CHARACTER SET utf8mb4 DEFAULT ENCRYPTION='N' COLLATE utf8mb4_unicode_ci;
  • later update of schemas
ALTER DATABASE h1k CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
ALTER TABLE Images CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  • backup DB
mysqldump -u root -p db_name > db_backup.sql
  • restore DB
mysql -u root -p < h1k_back.sql
  • database storage
/var/lib/mysql
  • user creation
SELECT user,plugin,host from mysql.user;

DROP USER 'username'@'localhost';
CREATE USER 'username'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'password';

GRANT ALL ON db_name.* to 'username'@'localhost';
FLUSH PRIVILEGES;
SHOW GRANTS FOR 'username'@'localhost';

Flutter

Widget / RenderObject / Lifecycle

Widget

  • levný na výrobu
  • při každém zavolání build metody se vlastně zahodí a vytvoří nový
  • je immutable
  • paralelně k widget tree existuje strom elementů a RenderObjectů
  • drží jen konfiguraci widgetu

Element

  • mutable
  • reprezentuje aktuální instanci widgetu
  • handluje life cycle widgetu a jeho závislosti ve stromu - kdo je parent, kdo je child
  • udržuje si referenci na aktuální widget a zároveň referenci na render object, který ma taky svůj strom
  • instance je pak buď StatelessElement nebo StatefullElement
  • při build metodě se volá canUpdate metoda, ktera zjišťuje jestli starý a nový widget mají stejný runtime typ a klíč (není-li klíč tak jen typ -> pokud jsou shodné tak není třeba zahazovat instanci Elementu a jen up datovat property -> je přece mutable -> tak samo se nezahodí render object -> úspora výkonu

RenderObject

  • zodpovědný za kreslení na convos

Best practices

  • části stromu, kde se odehrávají setState změny je nejlépe zabalit do custom widgetu a volat změny tam -> zmenší se scope setState a musí se updatovat menší část stromu
  • taktéž lepší custom widget než metoda tvořící strukturu widgetů -> stále patří do velkého scopu nadřazeného widgetu a updatují větší celek
  • Inherited Widget - vyvolává se přes statickou metodu get typicky
    • MediaQuery.of(context)

    • Provider.of(content)

    • toto volání nejen, že najde příslušný InheritedWidget ale zároveň zařadí volající widget do seznamu subsriberů, takže kdykoliv se v InheritedWidget změní stav, tak vyvolá rebuild i subsribovaných widgetů -> subsription dělat co nejníže ve stromu co to jde -> nebo vymezit jen oblast zájmu pokud to je InheritedModel, e.g. MediaQuery.sizeof(context) bude notifikovat jen při změně size propert

State lifecycle

stateDiagram-v2
    initState --> didChangeDependencies
    didUpdateWidget --> build
    didChangeDependencies --> build
    setState --> build
    build --> dispose

    note left of initState
      pouze jednou při mountování do stromu
    end note

    note left of didUpdateWidget
      při změně Widgetu
    end note

    note left of dispose
      při odstranění Ze stromu
    end note

    note left of didChangeDependencies
      při změně InheritedWidgetů na které jsme referencovali
    end note
  • v did metotách nevolat setState, zbytečně to duplikuje volání build metody
  • dispose musí uvolnit veškeré resourcy jako controllery, listenery, stream subscribery, jinak je garbage collector neuvolní a dojde k memory leaku
  • const třídy se stejnými argumenty budou mít v paměti pouze jednu instanci => const widget nevyvolá rebuild sebe a celého svého podstromu
  • totéž platí pokud je widget ve state třídě uložen jako final properta => odkazuje na stejné místo v paměti a framework widget ze stejné paměti nerebuilduje
  • repaintBoundary může obalit widget a říct RenderObjectu aby nešiřil needRepaint flag příliš daleko
  • Listy nejlépe přes itemBuilder a shrinkWrap = false, jinak rozbíjí 1azy loading => donutí vypočítat rozměry všech položek
    • cacheExtent definuje rozsah načteného obsahu itemBuilderu

State management

vanilla state management - pouziti nastroju, ktere dodava ciste framework bez pouziti reseni tretich stran

  • ephemeral state - docasny stav, ktery neprezije restart aplikace, byva lokalni k danemu widgetu, nikam se neuklada
  • application state - stav trvalejsiho razu, pres vice screen nebo widgetu, muze se ulozit a obnovit po restartu aplikace

Lifting up

  • komponenty musi sdilet nejaky stav/data (vice widgetu nebo screen)
  • je mozne instanci stavu presunout do state objektu jejich sdileneho parenta
  • vysledkem byva tesna zavislost (coupling) se spoustou vzajemnych callbacku predanych v konstruktoru widgetu
  • neda se moc dobre skalovat a pridavanim novych podminek vznika silene komplikovany chaos

Observer pattern

  • behavioralni pattern, klient se nechce cyklicky dotazovat, jestli uz nastal kyzeny stav, tak samo server(observable) nechce rozesilat info o zmene vsem komponentam v systemu (spoustu z nich by to bylo jedno)
  • komponenta obsahujici zajimavy stav (observable nebo publisher) implementuje List subscriberu a metody addListener, removeListener
    • v pripade zmeny stavu informuje vsechny subscribery pres dodany callback
  • komponenty zavisle na tomto stavu se zaregistruji (listener nebo subscriber)

Zajimave tridy

  • Listenable (abstraktni trida s addListener() a removeListener())
  • ValueListenable (pridava jen hodnotu typu T a jeji getter do Listenable)
  • ChangeNotifier (implementuje Listenable interface a pridava List _listeners metodu notifyListeners(), ktera notifikuje subscribery)
  • ValueNotifier (implementuje ChangeNotifier s jednou observable promennou typu T, implementuje take ValueListenable)
  • ValueListenableBuilder (widget, ktery zabaluje vsechno dohromady - konstruktor sezere ValueListenable a builder, ktery vyplivne child widget)
    • obvykle stav obsahuje vice promennych a pak se implementuje ChangeNotifier pro kazdou cast logiky - ma vice promennych definujicich stav a v prislusnych setterech nebo metodach vyvolava notifyListeners() metodu
    • widget vlastnici instanci ChangeNotifier musi na nem ve vlastnim dispose() take zavolat changeNotifier.dispose()
  • ListenableBuilder (handluje za nas pridavani/odebirani subscriberu, abchom je nezapomneli na spravnych mistech pridat/odebrat), na vstupu prebira obecny Listenable typ
    • zrejme sam sebe subscribuje a pokud dojde k notifikaci tak zavola na sobe setState, aby to zpropagoval do childa?

Inherited Widget

  • MediaQuery, Navigator a Theme jsou InheritedWidgety, ktere vklada do stromu WidgetsApp, ktery je vracen MaterialApp nebo CupertionApp
  • obsahuje bool updateShouldNotify(covariant InheritedWidget oldWidget), kde muzeme porovnat stary s novym po zmene a vyhodnotit, jestli dana zmena ma byt notifikovana (true)
  • pri implementaci definujeme statickou metodu of(), napr.:
class MediaQuery extends InheritedWidget {
    final MediaQueryData data;

    static MediaQueryData of(BuildContext context) {
        return context.dependOnInheritedWidget<MediaQuery>()!.data;
    }
}
  • dependOnInheritedWidget hleda InheritedWidget daneho typu ve stromu smerem nahoru az k rootu, pokud ho najde, tak vrati v tomto pripade data, jinak vyhlasi error
  • krom navraceni InheritedWidgetu taky registruje volajici widget do zavislosti na danem InheritedWidgetu, s kazdou zmenou se pak vyhodnoti updateShouldNotify a pripadne provede build zavislych widgetu (pres didChangeDependencies)

Boiler

3D tisk