Xfce4 brak powiadomień

W moim menadżerze okien, Xfce4, przestały działać powiadomienia. W ustawieniach, xfce4-notifyd-config, widnieje następujący komunikat:

Usługa powiadomień nie jest uruchomiona. Nie będą wyświetlane żadne powiadomienia.
The notification service is not running. No notifications will be shown.

Przestały się pojawiać jakiekolwiek powiadomienia z aplikacji, zero dymków itp. Dlaczego tak się stało, nie wiem ale pomogło wykonanie polecenia:

$ systemctl --user start xfce4-notifyd.service

A najlepiej dodać do autostartu. Pozostaje kwestia zdiagnozowania dlaczego przestało działać.

Bash i regexp

$ shopt compat31
compat31        off
$ if [[ "9" =~ "[0-9]" ]]; then echo match; else echo no match; fi
no match
$ shopt -s compat31
$ shopt compat31
compat31        on
$ if [[ "9" =~ "[0-9]" ]]; then echo match; else echo no match; fi
match

Katalog źródłowy dla skryptu

Pobrane ze stackoverflow:

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
  DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
  SOURCE="$(readlink "$SOURCE")"
  [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
done
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"

A można to użyć na przykład do wczytywania bibliotek dla skryptu.

#!/usr/bin/env bash

get_sh_directory() {
    local SOURCE DIR
    SOURCE="${BASH_SOURCE[0]}"
    while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
        DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
        SOURCE="$(readlink "$SOURCE")"
        [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
    done
    DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
    echo $DIR
}

LIB=$(get_sh_directory)

if [[ -n $LIB &&  -f "$LIB/lib/library.sh" ]]; then
    echo $LIB
    source $LIB/lib/library.sh
    do_it
fi

Oraz sama biblioteka:

do_it() {
    echo "I'm the library"
}

Wywołanie skryptu działa teraz jak poniżej:

dracorp@laptop:~  (master ✓) 0
$ test_lib.sh 
/home/dracorp/bin/poligon/sh/test_lib
I'm the library

Bash – nazwy funkcji

#!/usr/bin/env bash

function foo {
    echo foo
    echo "In function $FUNCNAME: FUNCNAME=${FUNCNAME[*]}" >&2
}

function bar {
    echo "$(foo) bar"
    echo "In function $FUNCNAME: FUNCNAME=${FUNCNAME[*]}" >&2
}

function method {
    echo "$(bar) method"
    echo "In function $FUNCNAME: FUNCNAME=${FUNCNAME[*]}" >&2
}

echo "=== Start ===="
echo "==== FOO ====="
foo
echo "==== BAR ====="
bar
echo "=== METHOD ==="
method
echo "=== Finish ==="

I wynik powyższego:

$ ./function.sh 
=== Start ====
==== FOO =====
foo
In function foo: FUNCNAME=foo main
==== BAR =====
In function foo: FUNCNAME=foo bar main
foo bar
In function bar: FUNCNAME=bar main
=== METHOD ===
In function foo: FUNCNAME=foo bar method main
In function bar: FUNCNAME=bar method main
foo bar method
In function method: FUNCNAME=method main
=== Finish ===

Można jeszcze wczytać i wykonać powyższy plik za pomocą . lub source:

$ . ./function.sh 
=== Start ====
==== FOO =====
foo
In function foo: FUNCNAME=foo source
==== BAR =====
In function foo: FUNCNAME=foo bar source
foo bar
In function bar: FUNCNAME=bar source
=== METHOD ===
In function foo: FUNCNAME=foo bar method source
In function bar: FUNCNAME=bar method source
foo bar method
In function method: FUNCNAME=method source
=== Finish ===

Ostatni element lub -1 tablicy wskazuje jak plik był przetworzony.

Bash – tworzenie aliasów

Tworzenie aliasów ale trochę bardziej dynamicznych. Na początku coś prostego:

f1() {
  local alias_name="${1:-pxx}"
  alias ${alias_name}='echo foo'
}
$ f1 bar
$ alias | grep bar
alias bar='echo foo'
$ bar
foo

A potrzebowałem tego dla modułu Perla local::lib:

__perl-local-lib() {
  local local_directory="${1:-$HOME/perl5/local-lib}"
  local alias_name="${2:-pll}"
  case $1 in
    -h|--help)
      printf '%s\n' "Usage: ${FUNCNAME[0]} [directory for local::lib] [alias name]"
      return;;
  esac

  if perl -I${local_directory}/lib/perl5 -Mlocal::lib=${local_directory} &>/dev/null; then
    alias ${alias_name}="$(printf '%s\n' "eval \"\$(perl -I${local_directory}/lib/perl5 -Mlocal::lib=${local_directory})\"")"
  fi
}

[Git] Zapobieżenie wychodzenia poza git-root

Na przykładzie Jenkinsa. Załóżmy, że katalog domowy usługi, /var/lib/jenkins jest zwersjonowany. Wewnątrz katalogu workspace dzieje się magia. Są w nim budowane zadania. Czasem coś zawiedzie ale polecenia gita dalej są wykonywane i psują katalog domowy. Aby temu zapobiec wystarczy (do zweryfikowania) wyeksportować zmienną GIT_CEILING_DIRECTORIES z wartością:

export GIT_CEILING_DIRECTORIES=/var/lib/jenkins

Należy użyć dwukropka (:) jako separatora.

[jenkins@laptop ~]$ cat .gitignore 
**.jar
**.jpi
workspace/
[jenkins@laptop bash-it]$ pwd
/var/lib/jenkins/workspace/bash-it
[jenkins@laptop bash-it]$ git st
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean
[jenkins@laptop bash-it]$ rm -rf .git
[jenkins@laptop bash-it]$ git st
On branch master
Changes not staged for commit:
  (use "git add ..." to update what will be committed)
  (use "git checkout -- ..." to discard changes in working directory)

	modified:   ../../.local/share/autojump/autojump.txt

Untracked files:
  (use "git add ..." to include in what will be committed)

	../../.bash_history
	../../.cache/
	../../.config/
	../../jobs/
	../../plugins/github-oauth/
	../../plugins/pipeline-github/
	../../queue.xml
	../../secrets/hudson.console.AnnotatedLargeText.consoleAnnotator
	../../secrets/hudson.console.ConsoleNote.MAC

no changes added to commit (use "git add" and/or "git commit -a")
[jenkins@laptop bash-it]$ export GIT_CEILING_DIRECTORIES=/var/lib/jenkins
[jenkins@laptop bash-it]$ git st
fatal: Not a git repository (or any of the parent directories): .git

vim – sprawdzenie wersji i patch

Sprawdzenie w Vim konkretnej wersji lub/i wersji patcha. Dla przykładu w wersji 7.4.330 wprowadzono matchaddpos():

if version > 704 || version = 704 && has('patch330'))
endif

lub

if has('patch-7.4-775')
endif

Git fork i upstream

Wstępne założenie: rozdzielenie projektu i osobna dalsza praca.

Na Github robię rozgałęzienie kodu, tzw. fork. Następnie klonuję repozytorium na lokalny system plików:

git co https://github.com/dracorp/shell-includes.git

Pracuję z kodem, nanoszę zmiany itp. Jednak chciałbym zaciągnąć zmiany z oryginalnego lub je tylko podejrzeć. W tym celu dodaję nowe nowe zdalne repozytorium wskazujące na oryginalne:

git add remote upstream https://github.com/l0b0/shell-includes.git

Teraz mogę zaciągnąć zmiany do np. nowej gałęzi:

git fetch upstream
git co -b upstream upstream/master
git diff master

Ostatnie polecenie pokaże mi różnice pomiędzy moim a „oryginalnym” kodem.

[Perl]Weryfikacji parametru dla Getopt

#!/usr/bin/env perl

use strict;
use warnings;
use utf8;
use English qw( -no_match_vars);
use Carp;
use Data::Dumper;
use feature qw(say);
use Getopt::Long;
use Log::Log4perl qw(:easy);
Log::Log4perl->easy_init($ERROR);
use Pod::Usage;

my $option = {
};

sub parseCommandLine {
    my ( $option ) = @ARG;
    my $fileHandler = sub {
        my $file = $ARG[1];
        if ( -e $file ) {
            $option->{file} = $file;
        }
        else {
            ERROR "File '$file' does not exist";
        }
    };
    GetOptions(
        'f|file=s' => $fileHandler,
    );

}
parseCommandLine($option);
print Dumper $option;

I wynik dla:

$ ./getopt.pl -f getopt.pl
$VAR1 = {
          'file' => 'getopt.pl'
        };
$ ./getopt.pl -f getopt.p
2017/10/09 23:26:18 File 'getopt.p' does not exist
$VAR1 = {};

Ale gdy zamienić my $fileHandler na sub fileHandler i podmienić referencję w GetOptions z $fileHandler na \&fileHandler to otrzymamy następującą informację:

./getopt.pl -f getopt.pl
Variable "$option" will not stay shared at /home/dracorp/bin/poligon/perl/getopt.pl line 23.
$VAR1 = {
          'file' => 'getopt.pl'
        };

Więcej na perldiag.

Uruchomienie skryptu w czystym środowisku

Ostatnio miałem potrzebę uruchomienia skryptu w środowisku w którym są wyeksportowane zmienne środowiskowe których bym nie chciał mieć w powłoce danego skryptu. Jedna z możliwości to użycie poniższego zapisu:

#!/usr/bin/env bash
[[ -n "$HOME" ]] && exec /usr/bin/env -i bash --noprofile --norc "$0" "$@"
printf "%s:\n" 'Export'
export
printf "%s:\n" 'Env'
env
$ ./run.sh
Export:
declare -x OLDPWD
declare -x PWD="/home/dracorp/bin/poligon"
declare -x SHLVL="1"
Env:
PWD=/home/dracorp/bin/poligon
SHLVL=1
_=/usr/bin/env

W shebang niestety nie można użyć zapisu env -i bash. Nie jest to jeszcze to co bym chciał.
cdn.