Koncem prosince 2020 proběhlo vyasfaltování cyklozteky od „Železňáku“ do Křtětic. Vyasfaltovaná cesta je bez převýšení, dlouhá 1,25km. Vhodná pro inline brusle, jízdu na kole a procházku.

PM2 (Process Manager 2) je správce procesů pro Node.js, který vám pomůže spravovat a udržovat vaše aplikace v chodu. Pojďme se podívat na základy.
npm install pm2 -g
pm2 start app.js
$ pm2 restart app_name
$ pm2 reload app_name
$ pm2 stop app_name
$ pm2 delete app_name
app_name nahraďte:
Krásně vidíte status aplikace, přidělený výkon procesoru a paměti
pm2 [list|ls|status]
pm2 logs
Zobrazení staršího logu:
pm2 logs --lines 200
pm2 monit
Doba pokročila, přihlašování na server přes jméno a heslo není nejbezpečnější a je zbytečně zdlouhavé. Nyní si v cloudu vytvoříte server na pár kliknutí a následně se na něj přihlásíte přes SSH klíč. Je to bezpečné a rychlé.
Potřebujete vygenerovat soukromý a veřejný klíč. Soukromý klíč umístíte na klienta, ze kterého se přihlašujete a veřejný klíč na server, na který se přihlašujete. Při inicializaci spojení vám server pošle data, která zašifrujete soukromým klíčem, a server po rozšifrování veřejným klíčem získá původní data. Tím ověří, že máte správný soukromý klíč a povolí vám přístup.
Soukromý klíč v žádném případě nesmíte nikomu poskytnout, ten si chraňte!
K veřejnému klíči se může dostat kdokoliv. V případě napadení serveru, není problém když se útočník dostane k veřejnému klíči.
Pojďme vygenerovat soukromý a veřejný klíč – to většinou budeme dělat na klientu.
ssh-keygen -t rsa
Výstup bude podobný tomuto -toto není výstup pro klíč, který používám :-):
root@vencax-virtual-machine:/home/venca-x# ssh-keygen -t rsa Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /root/.ssh/id_rsa Your public key has been saved in /root/.ssh/id_rsa.pub The key fingerprint is: SHA256:wV81a776hOaU5Gtj5vVtWhujL2hUJn53H4XsdL3dG72 root@vencax-virtual-machine The key's randomart image is: +---[RSA 3072]----+ | .+,G| | +.PRX| | =oxR| | . . --A| | S . l.x+| | .+. =E+| | .+.F.o=.| | .o.- .| | .=a. | +----[SHA256]-----+
Budete vyzváni, zda se má veřejný klíč uložit do výchozího umístění (/root/.ssh/id_rsa) – stačí potvrdit <ENTER>
Dále budete vyzváni pro zadání passphrase (hesla k certifikátu). Toto heslo není povinné. nicméně doporučuji jeho zadání pro případ kdyby se někdo dostal k privátnímu klíči.
Tím se klíče uloží do umístění: /root/.ssh/
Klientská část je hotova. Nyní nahrajeme veřejný SSH klíč na server, ke kterému se budeme připojovat. Můžeme nahrát stejný veřejný klíč na všechny servery, na které se chceme připojit.
ssh-copy-id -i ~/.ssh/id_rsa.pub user@host.com
Ukázka výstupu:
root@vencax-virtual-machine:~/.ssh# ssh-copy-id -i ~/.ssh/id_rsa.pub user@host.com /usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub" /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys user@host.com's password: Number of key(s) added: 1 Now try logging into the machine, with: "ssh 'user@host.com'" and check to make sure that only the key(s) you wanted were added.
Na serveru se podívejte do souboru .ssh/authorized_keys, ve kterém byste měli vidět přidaný veřejný klíč z klienta
Na serveru nyní zapneme přihlášení přes SSH klíč a zakážeme přihlášení přes jméno a heslo. To provedeme v souboru:
vim /etc/ssh/sshd_config
Povolení přihlášení přes SSH klíč:
RSAAuthentication yes PubkeyAuthentication yes
Zakázání přihlášení přes SSH přes jméno a heslo:
ChallengeResponseAuthentication no PasswordAuthentication no UsePAM no PermitRootLogin no
Nakonec restartujeme SSH:
systemctl restart sshd.service
Tím máme hotovo. Restartem SSH stále zůstáváme připojení k serveru, než otestujete správnou funkčnost přes SSH klíče, se raději neodpojujte :-)
Připojení z linuxu nám funguje, trochu problém nastává u připojení přes Putty. Nyní máme soukromý klíč ve formátu OpenSSH a musíme ho převést na .ppk
Spustíme program PuTTYgen – už je předinstalovaná ve WIndows 10?
Do programu PuTTYgen naimportujeme náš soukromý klíč (id_rsa) File -> Load private key
Načtený soukromý klíč uložíme tlačítkem Save private key -> například jako id_rsa.ppk
Tento výsledný id_rsa.ppk vložíme k našemu připojení v Putty: Connection -> SSH -> Auth -> Private key for authentication
Dnes jsme si ukázali bezpečnější, rychlejší a modernější způsob přihlášení na server přes SSH. Už se nemusíte bát o svá hesla, jejich pravidelnou změnu a brutal force útok pro prolomení hesla.
Pokud máte VPS s Ubuntu a z nějakého důvodu potřebujete grafický desktop, vyhází mi výkonově nejlépe LXDE + X2Go.
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install lxde
sudo apt-get install software-properties-common
sudo add-apt-repository ppa:x2go/stable
sudo apt-get install x2goserver x2goserver-xsession
Zkontrolujeme status X2Go:
systemctl status x2goserver
V mém případě se budu připojovat z Windows, klienta stáhnu z https://wiki.x2go.org/doku.php/download:start (X2Go Client -> mswin)
1) editujeme soubor /root/.profile
2) zakomentujeme řádek: mesg n || true (komentář je #), takže: #mesg n || true
3) přidáme: tty -s && mesg n
Přeskočíme kecy o botech a rovnou se pustíme do práce. Největší platformou pro chatovací boty s otevřeným API nabízí Telegram. Dnes si ukážeme, jak si vytvořit bota, který bude interagovat na uživatelovo požadavky.
Všechny boty vytváříme u toce botů – BotFather. Uděláme to tak, že v seznamu konverzací vyhledáme BotFather. V detailu konverzace vytvoříme nového bota příkazem /newbot a postupujeme podle pokynů.
Budete vyzváni na jméno bota (libovolné znaky včetně diakritiky) a následně na uživatelské jméno bota: slovo bez diakritiky, mezer s příponou bot nebo _bot. Uživatelské jméno musí být v celém Telegramu jedinečné.
Po vytvoření bota bude zobrazeno jeho API access token – dále jen token. Ten si pečlivě uchovejte a nikomu ho nesdělujte – slouží k ovládání bota.
V Telegramu existují dva způsoby, jak získat zprávy poslané botovi: long polling a webhooks
Při tomto přístupu se periodicky doptáváte API Telegramu na nové zprávy. Musíte vhodně nastavit periodu doptávání se na nové zprávy.
Při tomto přístupu je při každé interakci s botem zpráva odeslaná i na náš server. Tento přístup mám raději, protože vypadá jako komunikace v reálném čase.
V tomto článku si popíšeme použití webhooks. Pro použití webhooks potřebujeme php script, který běží na veřejné adrese s HTTPS certifikátem. Pro naši ukázku například: https://www.venca-x.cz/bot/pocasi.php
Teď trochu přeskočíme obsah souboru pocasi.php a rovnou tento script zaregistrujeme aby byl zavolán a přijal zprávu od našeho bota. To provedeme příkazem:
https://api.telegram.org:443/bot[token]/setwebhook?url=https://www.venca-x.cz/bot/pocasi.php
Příkaz zadáme do URL v prohlížeči. Měli bychom obdržet hlášku s úspěšným nastavením webhooku:
{"ok":true,"result":true,"description":"Webhook was set"}
Zahájíme chat s uživatele BotFather, kterému pošleme následující požadavky
/newbot
Budete vyzváni pro přesdívku bota a následně budete vyzváni pro zadání uživatelského jména bota. Uživatelské jmeno musí končit na slovo „bot“.
Po vytvoření bota získáte token pro přístup k API Telegramu. Token si pečlivě uložte, budeme ho potřebovat.
Nyní botovi musíme nastavit URL adresu, na kterou bude přeposílat požadavky. Do vašeho prohlížeče zadáme následující URL adresu:
https://api.telegram.org/bot*TOKEN*/setwebhook?url=*https:/ /example.domain/path/to/bothook.php*
Slovo *TOKEN* nahraďte API tokenem, získaným při vytvoření bota.
*https:/ /example.domain/path/to/bothook.php* nahraďte vaší adresou, kde jsme zprovoznili jednoduchou ukázku vracející JSON.
Bota máme vytvořeného, zaregistrovaný webhook, který nám přeposílá zprávy poslané botovi. Pojďme bota oživit aby zprávy zpracovával a reagoval na ně.
Pro práci s bot API se mi zalíbila knihovna telegram-bot/api nainstalujeme ji:
composer require telegram-bot/api
Super, konečně jsme se dostali na příjem zpráv a reagování na ně. Na zprávu /ping odpoví bot zprávou pong:
<?php
require_once "vendor/autoload.php";
try {
$bot = new \TelegramBot\Api\Client('YOUR_BOT_API_TOKEN');
$bot->command('ping', function ($message) use ($bot) {
$bot->sendMessage($message->getChat()->getId(), 'pong!');
}); $bot->run();
} catch (\TelegramBot\Api\Exception $e) {
$e->getMessage();
}
Nezapomeňte místo YOUR_BOT_API_TOKEN nastavit váš token z vytváření bota.
Bota můžeme ovládát i přes speciální klávesnici pro rychlé volby. Po zadání příkazu /start přivítáme návštěvníka a zobrazíme mu klávesnici s rychlou volbou:
$bot->command('start', function ($message) use ($bot) {
$keyboard = new \TelegramBot\Api\Types\ReplyKeyboardMarkup(array(array("/pocasi", "/ping")), true);
$bot->sendMessage($message->getChat()->getId(), 'Vítejte počasí', null, false, null, $keyboard);
});
Načítání obsahu webových stránek bez nutnosti obnovení stránky prostřednictvím AJAXového volání je dnes běžnou praxí.
Zavést toto funkčnost web postaveném na Nette frameworku, je velice jednoduché a rychlé. Ukážeme si jak na to s ajaxovou knihovnou s názvem Naja. Pokud děláte úplně nový projekt, doporučuji Nette 3.0, zapomeňte na nette.ajax.js ale rovnou použijte Naju. Nette,ajax.js je již „hotový“ a dál se nevyvijí. Naja je jeho nástupce.
npm install naja –save-dev
Pro sloučení všech js souborů a jejich minifikaci používám Gulp. V Gulp tasku přidáme Naja.js do našeho jednoho velkého minifikovaného main.min.js souboru:
var uglify = require('gulp-uglify-es').default;
//…..
gulp.task('jsMain', done => {
gulp
.src(['node_modules/jquery/dist/jquery.min.js',
'node_modules/popper.js/dist/umd/popper.min.js',
'node_modules/bootstrap/dist/js/bootstrap.min.js',
'node_modules/tether/dist/js/tether.min.js',
'node_modules/naja/dist/Naja.js',
'venor/nette/forms/src/assets/netteForms.min.js',
'src/js/main.js'], {allowEmpty: true})
.pipe(uglify({
mangle: false,//disable rename variables and functions
}))
.pipe(concat('main.min.js'))
.pipe(gulp.dest('www/js'));
done();
});
TIP: je potřeba použít knihovnu gulp-uglify-es ( gulp-uglify nestačí)
npm gulp-uglify-es --save-dev
Pak jen jednoduše tento 1 minifikovaný JS vložíme do šablony:
<script src="{$basePath}/js/main.min.js"></script>
Do souboru /src/js/main.js (který se také přidává do main.min.js přidáme tento kód pro inicializaci Naji):
document.addEventListener( 'DOMContentLoaded', () => { naja.initialize(); } );
A máme hotovo. Nyní jen přidáme class=“ajax“ prvků, které chceme mít ajaxově, stejně jako u Nette.ajax.js
Po kliknutí na tlačítko aktualizujeme ajaxem snippet, ve kterém se překreslí aktuální datum. Jednoduché 🙂
Presenter:
<?php declare(strict_types=1); namespace App\FrontModule\Presenters; use App; use Nette\Utils\DateTime; class HomepagePresenter extends BasePresenter { private $dateTime; public function handleActualiseDateTime() { $this->dateTime = new DateTime(); if ($this->isAjax()) { $this->redrawControl('dateTimeSnippet'); } } public function renderDefault(): void { if ($this->dateTime === null) { $this->dateTime = new DateTime(); } $this->template->dateTime = $this->dateTime; } }
Šablona:
<div class="col-12"> <hr/> {snippet dateTimeSnippet} {$dateTime|date:'j. n. Y H:i:s'} {/snippet} <a n:href="actualiseDateTime!" class="ajax">AKTUALIZOVAT</a> </div>
Jak se v gitu přepnout na verzi s posledním tagem?
#!/bin/bash
...
latesttag=$(git describe --tags)
echo checking out ${latesttag}
git checkout ${latesttag}
Testujete? Já se o to pokouším. Pro komplexnější testování UI prvků aplikace doporučuji nástroj Espresso.
Pokud vytvoříte v Android Studiu nový projekt, máte základ připraven. Android Studio vytvoří základní strukturu a základní testy automaticky. Jedná se o složky:
Naše Espresso testy tedy budeme umísťovat do složky androidTest. Pro první test stačí do souboru build.gradle (ve složce app) přidat závislost:
androidTestImplementation 'com.android.support.test:rules:1.0.2'
Můj build.gradle vypadá takto:
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "cz.vencax.hellobuild"
minSdkVersion 15
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
androidTestImplementation 'com.android.support.test:rules:1.0.2'
}
Pojďme vytvořit náš první Espresso test. Otestujeme, zda TextView obsahuje text Hello World!
package cz.vencax.hellobuild;
import android.support.test.filters.LargeTest;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import org.junit.After;
import org.junit.Before;
import org.junit.FixMethodOrder;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.containsString;
@RunWith(AndroidJUnit4.class)
@LargeTest
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class FirstTest {
@Rule
public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>(MainActivity.class);
@Before
public void setUp() throws Exception {
//Before Test case execution
}
@Test
public void test1ChatId() {
//onView(withId(R.id.helloTextView)).check(matches(isDisplayed()));
onView(withId(R.id.helloTextView)).check(matches(withText(containsString("Hello World!"))));
}
@After
public void tearDown() throws Exception {
//After Test case Execution
}
}
Test spustíme kliknutím pravým tlačítkem na soubor s testem v levé části Android Studia – Project. Nebo z příkazové řádky:
gradlew connectedAndroidTest
Azure DevOps je sklělý nástroj pro vývojáře. Nabízí ZDARMA soukromé git repozitáře, nástroj pro tasky (řízení práce), a build nástroje. To vše „zdarma“. Kompletně jsem na tuto platformu přešel a jsem maximálně spokojený. Android aplikace automaticky po pushi do Gitu otestuji, provedu build a vydám novou vývojovou verzi. Build agent má však omezení na běh max. 10h/měsíc, na malé projekty bohatě dostačuje. Pokud jste náročnější a tento limit vám nestačí, jednoduše nainstalujete na svůj server svého soukromého agenta, který provádí build. Pak jste omezeni pouze výkonem vašeho serveru. Pojďme si zprovoznit soukromého agenta pro build Android aplikace:
Stáhneme a nainstalujete Java SDK
Stáhneme a nainstalujeme Android Studio
Pro build je nutné přidat do path následující proměnné: java, JAVA_HOME, JDK, AndroidSDK
Jak zjistím kde mám nainstalován Android SDK abych ho přidal do Path?
Android Studio -> Menu -> Tools -> SDK Manager -> položka Android SDK Location.
Do Uživatelsky definovaných proměnných v mém případě přidáme Název proměnné: ANDROID_HOME a Hodnota proměnné: C:\Users\Test\AppData\Local\Android\Sdk
do Path stejným způsobem přidáme ještě tyto hodnoty:
java : C:\Program Files\Java\jdk-11.0.2
JAVA_HOME : C:\Program Files\Java\jdk-11.0.2
JDK : C:\Program Files\Java\jdk-11.0.2
Po přidání mi build ještě nefungoval, bylo nutné provést restart zařízení.
Pro build by v cmd mělo fungovat (spustíme v root android projektu):
gradlew assembleDebug nebo gradlew assembleRelease
Nejprve musíme vytvořit token pro autentizaci agenta. Přihlásíme se do TFS a vpravo nahoře klikneme na uživatele -> Security ->Personal access tokens -> New Token. Vytvoříme nový token, kterému nastavíme expiraci (jde na max 1 rok?) a oprávnění. Zobrazí se nám token, který si uschovejte, budeme ho potřebovat pro agenta.
Na URL https://dev.azure.com/{your_organization}/_admin/_AgentPool (v mém případě je {your_organization} venca-x). Zde vidíme seznam agentů a jejich stav. Pro vytvoření nového agenta klikneme na tlačítko Download agent. Vybereme cílovou platformu a nainstalujeme podle postupu. Po nainstalování není nutné spouštět agenta jako administrátor. Instalace probíhá přes Windows PowerShell.
Jděte na adresu:
https://dev.azure.com/{your_organization}/_admin/_AgentPool kde v sekci Default vidíte vaše soukromé agenty a jejich stav. Po kliknutí na Capabilities vidíte všechny vlastnosti daného agenta. Zde je důležité aby byly vlastnosti:
java, JAVA_HOME, JDK, AndroidSDK