Pasuspender

Pulseaudio jest super: przycisza mi muzykę, kiedy ktoś gada przez komunikator, mogę ustawić głośność każdego programu z osobna, obsługuje świetnie interfejsy audio usb . Początkowo miało sceptyków, ale na co dzień nic lepszego nie jest mi potrzebne i niczego lepszego zwyczajnie nie ma. Na co dzień. Czasami jednak wolę, kiedy program, na przykład Audacity, ma dostęp do wszystkich urządzeń dźwiękowych.

Wówczas przydaje się pasuspender, który odcina Pulseaudio od podanego procesu, ale pozwala mu działać na pozostałych. Robi się to tak: pasuspender audacity, po czym uruchamiam Audacity, gdzie mogę przebierać we wszystkich wejściach i wyjściach dźwięku, jakie widzi stara, poczciwa ALSA.

Nextcloud 16 i Kalendarz

Ostatnio aktualizowałem NextClouda do wersji 16 i podczas aktualizacji otrzymałem informację o niekompatybilności kalendarza z wersją 16. Okazało się, że nie jest tak źle. Po aktualizacji NextClouda zaktualizowałem Kalendarz w aplikacjach i włączyłem go w Twoich Aplikacjach.

Jak po każdej aktualizacji, warto przejść się do katalogu z zainstalowanych Nextcloudem i dodać brakujące indeksy do bazy danych:

sudo -u [uzytkownik] php occ db:add-missing-indices

Po aktualizacji autorzy NextClouda zwrócili moją uwagę, że baza danych nie jest skonfigurowana dla obsługi znaków 4-bajtowych, więc emotikonki nie będą działać. Znak czasów…

Nowy, stary NetGear

Mam w domu nowe zwierzątko. Wygląda jak 24-portowy switch i w zasadzie to nim jest.

NetGear i pierwsze kabelki

Nie jest to najnowszy model Wystarczy wspomnieć, że tylko cztery porty są gigabitowe. No ale jest zarządalny, ma VLANy, można go klastrować (chociaż ze zdjęcia nie wynika, żeby szybko mi to groziło). Ma też charakterystyczne dla starszych modeli diody ponad gniazdami. Zdecydowanie wolę tabelki po lewej stronie przedniego panelu.

Nie podłączyłem jeszcze wszystkiego, gdyż niektóre kabelki były wymierzone idealnie pod poprzednika i są teraz za krótkie. W przyszłym tygodniu się nadrobi.

Jestem ogólnie zadowolony, bo dotychczas używałem dwóch tanich, domowych switchy Dlinka i zwyczajnie z wolnym portami było już krucho. No i lepiej mieć jedno urządzenie, zawsze odrobina mniej kabli pod biurkiem.

Trochę się nad tym posiedzi.

Oczywiście konfigurować można to cały dzień mi jeszcze trochę. Zobaczymy, co się z tego uda wycisnąć.

Fedora 30

Fedora 30 jest już w becie i szykują się do zamrożenia wersji pakietów. Zespół RPMFusion przygotował już repozytoria pełne kodeków oraz multimediów. Czas więc na aktualizację.

Przed usunięciem fedora-release dobrze sprawdzić, które z tych pakietów są zainstalowane:

rpm -qa | grep release

# rpm -e --nodeps fedora-release fedora-release-notes fedora-release-server fedora-release-workstation
# dnf install --allowerasing --releasever=30 fedora-gpg-keys fedora-release
# rpm -Uvh https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-branched.noarch.rpm https://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-30.noarch.rpm
# yum update
# reboot

Przy w miarę szybkim łączu oraz dysku ssd całość zajmuje 15 minut, w czasie których można bez przeszkód pracować.

LibreOffice z Rawhide

Jest sobie Fedora 29 i jest Libre Office 6.2. Pozornie patowa sytuacja, bo nowego Libre dostanie Fedora 30, a ja chcę teraz. Mam kilka możliwości. Mogę ściągnąć program jako Flatpaka, albo Snapa. Jeżeli jednak mam do wyboru program z repozytorium, to wolę rpmy.

Zajrzymy do Rawhide i „pożyczymy” sobie z niego LibreOffice. Potrzebujemy pliku /etc/yum.repos.d/fedora-rawhide.repo:

[rawhide]
name=Fedora - Rawhide - Developmental packages for the next Fedora release
failovermethod=priority
baseurl=http://download.fedoraproject.org/pub/fedora/linux/development/rawhide/Everything/$basearch/os/
metalink=https://mirrors.fedoraproject.org/metalink?repo=rawhide&arch=$basearch
enabled=0
metadata_expire=6h
repo_gpgcheck=0
type=rpm
gpgcheck=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$releasever-$basearch
skip_if_unavailable=False

Usunąłem LibreOffice, żeby zależności również mieć z Rawhide:

sudo dnf remove *libreoffice*

A potem zainstalowałem nowszego:

sudo dnf --enablerepo=rawhide install libreoffice-writer libreoffice-calc libreoffice-impress libreoffice-langpack-pl

I na tym koniec. Plik fedora-rawhide.repo można zostawić tak jak jest, ponieważ ma linijkę enabled=0. Przy aktualizacji Fedory z czasem wersja stable nadgoni Libre Office i zaktualizuje go jak każdy inny pakiet.

Aktualizacja do Nextcloud 14

Jeżeli hostujesz Nextclouda 13 i skrypt sam z siebie nie wykrywa dostępnej aktualizacji do wersji 14, wszystko jest w porządku. Wersja 14.0 miała mały błąd, pojawiający się na kontach użytkowników ze spacją w nazwie. Wszystko jest naprawione, ale aktualizacje wydawane są „falami” dla kont i hostingów przewidzianych w nie wiem jaki sposób.

Można to obejść przełączając się na kanał beta w aktualizacjach. W kanale beta na obecną chwilę jest wersja 14.0.3, do której aktualizujemy Nextclouda tak, jak zawsze. Jeżeli używasz mailera z PHP do zmiany haseł i innych powiadomień, dostaniesz informację o konieczności wybrania innego serwera pocztowego. Może to być cokolwiek, konfiguruje się to tak samo jak Thunderbirda, Outlooka, czy Evolution.

Po aktualizacji możemy zmienić nasz kanał aktualizacji do stable, które niebawem nadgonią obecnie zainstalowaną wersję. Jeżeli brakuje nam miejsca na dysku, warto też usunąć stare kopie zapasowe z katalogu nextcloud/data/updater-[losowe_znaki]/backups/. Ja zawsze zostawiam tylko jeden, czy dwa ostatnie, gdyż zajmują sporo miejsca.

Nextcloud i Nautilus

Gnomowy menedżer plików ma kilka zalet, na przykład umiejętność podpinania się pod wszelkiego rodzaju zasoby sieciowe, bez potrzeby dłubania w /etc/fstab.

Z Nextcloudem może być trudniej, bowiem, w przypadku samodzielnego wygenerowania sobie certyfikatu ssl do bezpiecznych połączeń (a tak u mnie jest) Gnomowy kreator Konta Online odmawia współpracy z certyfikatem nieznanego pochodzenia. Na szczęście można wklepać ścieżkę do Nautilusa i działa. Jaka to ścieżka?

davs://domena.pl/remote.php

Nautilus również zwróci uwagę, że certyfikat pochodzi z nieznanego źródła, ale pliki pokaże. Login i hasło są takie same, jak logowanie do Nextclouda.

Mała strona z Pythonem

Ostatnio dłubię sobie stronę do obsługi programu javowego MegaMek. Jest tutaj: https://github.com/seem8/astech. Oczywiście pierwszym problemem było: w jakim pythonowym frameworku to zrobić? Jest Django, jest Flask, jest Bottle, jest Cherrypy, jest Pyramid i jeszcze jakieś 20 działających.

Zauważyłem, że są generalnie dwie kategorie stron internetowych:

  • operujące na dużych ilościach danych,
  • robiące coś fajnego.

Najistotniejsze w pierwszej kategorii jest utrzymanie spójności danych i bardzo szybkie na nich operowanie. Mamy kolekcję rzeczy, albo sklep, albo terminarz, albo bardzo dużo plików, albo coś takiego. I wówczas lepiej sprawdzają się duże frameworki, które pozwalają na tym się właśnie skupić, upraszczające tworzenie formularzy, wyszukiwarek, itp…

W drugiej kategorii ważne jest pozostawienie programiście swobody i generalnie zostawienie go w spokoju. Zauważyłem, że bardzo to lubię. Dlaczego? Bo można po prostu programować w Pythonie i nie przejmować się w ogóle faktem, że będzie to obsługiwane przez przeglądarkę.

Przedstawiam małe demo, które obrazuje powyższe:

#!/usr/bin/env python3

def read_logs(log_file):

  try:
    open(log_file,'r').close()
  except FileNotFoundError:
    open(log_file,'w').close()
    
  with open(log_file,'r') as myfile:
    mylines = myfile.readlines()
    lastlog = mylines[len(mylines)-50 : len(mylines)]
    lastlog.reverse()

    return lastlog

Powiedzmy, że mamy coś takiego. Zwykły kod, który działa wszędzie. Skorzystajmy więc z tej funkcji w programie tekstowym:

#!/usr/bin/env python3

def read_logs(log_file):

  try:
    open(log_file,'r').close()
  except FileNotFoundError:
    open(log_file,'w').close()

  with open(log_file,'r') as myfile:
    mylines = myfile.readlines()
    lastlog = mylines[len(mylines)-50 : len(mylines)]
    lastlog.reverse()

    return lastlog


important_logs = read_logs('journal.txt')

for i in important_logs:
  print(i)

Znowu nic niezwykłego. Wczytałem fragment logów systemowych i wypisałem 50 ostatnich linijek, korzystając z funkcji read_logs. Teraz zróbmy tak samo, ale żeby logi pokazywały się na stronie interenetowej.

#!/usr/bin/env python3

from bottle import template, route, run
def read_logs(log_file):

  try:
    open(log_file,'r').close()
  except FileNotFoundError:
    open(log_file,'w').close()

  with open(log_file,'r') as myfile:
    mylines = myfile.readlines()
    lastlog = mylines[len(mylines)-50 : len(mylines)]
    lastlog.reverse()

    return lastlog

@route('/')
def index_page():
  important_logs = read_logs('journal.txt')
  return template('index_page', logs=important_logs)

run(host='localhost', port=8080)

Tyle Pythona. Bottle używa dekoratorów, żeby określić jaki rodzaj funkcji deklarujemy: get, post, route, czy jeszcze jakiś inny. Jako „parametr” dekoratora wpisujemy ścieżkę, którą wpiszemy do przeglądarki. W tym wypadku po wpisaniu w pasek adresu localhost:8080 pokażą się nasze logi. Template potrzebuje co najmniej jednej informacji: jak ma się nazywać plik z końcówką .tpl, w którym będzie kod html. Oprócz tego możemy przekazać dowolną ilość argumentów, które pozwolą szablonowi na dostęp do naszych zmiennych oraz funkcji. Zmienna jest dla szablonu, a wartość to coś z naszego kodu Pythona, którą może być wszystko: zmienna, funkcja z parametrami, egzemplarz klasy, czy cokolwiek sobie umyślimy.

Musi to być jeszcze zrozumiałe dla przeglądarki, więc mamy do tego, wspomniany w kodzie, osobny plik index_page.tpl:

<html>
<head>
<title>Important Logs</title>
<head>
<body>

% for i in logs:
<p>{{i}}</p>
% end

</body>
</html>

Jest tutaj odrobina magicznych rzeczy:

  • znakiem % rozpoczynamy linijkę zawierającą kod Pythona,
  • na zmiennych w kodzie html operujemy poprzez konstrukcję {{zmienna}},
  • jako, że html ignoruje białe znaki, a Python ich właśnie używa do „kończenia” instrukcji for/if/def/itd…, korzystamy ze słowa kluczowego end, żeby wyjść z pętli.

Ścieżką może to być ‚/’, ‚/login’, albo ‚/read_logs/<log_file>’, co pozwala na przekazywanie argumentów na poziomie hiperłączy. Mógłbym więc rozpisać funkcję index_page w ten sposób:

@route('/read_logs/<log_file>')
def index_page(log_file):
  important_logs = read_logs(log_file)
  return template('index_page', logs=important_logs)

Wówczas łącze do przeglądarki wyglądałoby tak: http://localhost:8080/read_logs/journal.txt. Oczywiście jeżeli pozostawiamy cokolwiek użytkownikowi, zwłaszcza w internecie, trzeba się odpowiednio zabezpieczyć, ale o ciasteczkach i logowaniu napiszę innym razem.

Jeżeli ktoś widział kiedyś kod Django, to zapewne czuje już różnicę. To jest bardzo, bardzo proste. Pozwala mi skupić się na logice programu, który czasem robi dziwne rzeczy i nie stawia mi na drodze plików konfiguracyjnych oraz mnóstwa modułów. W dużym programie prędzej czy później taka swoboda odbija się czkawką (i poczułem to na sobie), ale w małym programie, tak do 1000 wierszy, robi świetną robotę.