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.

Reklamy

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.

System UIDs inconsistent

mosnter-uids

System UIDs inconsistent

UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.

Przy uruchomieniu telefonu przywitał mnie taki komunikat. Czyszczenie partycji data nie było brane pod uwagę.

Znalazłem informację żeby sprawdzić zawartość /data/system/uiderrors.txt. U mnie było:

11.10.2016 21:14: Package de.robv.android.xposed.installer has mismatched uid: 10075 on disk, 10142 in settings

Odinstalowałem więc aplikację:

root@Pentagram:/data/app # pm uninstall de.robv.android.xposed.installer
Success

Z poziomu samego telefonu nie mogłem tego zrobić. Aczkolwiek pewnie może by się dało bez odinstalowania ale już po fakcie.

Unicode Byte Order Mark (BOM)

Rozpoznanie BOM w zależności od kodowania:

Bytes         | Encoding Form 
--------------+------------------------
00 00 FE FF   | UTF-32, big-endian 
FF FE 00 00   | UTF-32, little-endian 
FE FF         | UTF-16, big-endian 
FF FE         | UTF-16, little-endian 
EF BB BF      | UTF-8 

Wykrycie BOM:

`xxd -l 3 -p filename` == efbbbf

cdn.

Android – „out of space” podczas instalacji pakietu

Krótkie wprowadzenie:
Aktualnie jestem w posiadaniu telefonu Pentagram Monster X5 Pro. Wybrałem go ze względu na dużą baterię 6000mAh. Z czasem jednak okazało się że telefon nie jest idealny, system od producenta nieaktualizowany a ciągłe zwiechy bywają uciążliwe. Dlatego aktualnie testuję inne ROMy i a na tą chwilę sprawdzam CyanogenMod 11.Do kopii ustawień jak i samych pakietów używam Super Backup.

Jednak ostatnio nie mogłem przywrócić wszystkich aplikacji np Smart AudioBook Player. Podczas instalacji czy to z poziomu SuperBackup czy sklepu dostawałem informację o zbyt małej ilości wolnego miejsca na urządzeniu.

Z poziomu adb komunikat był trochę inny:

adb install 'Smart AudioBook Player_3.1.3.apk'
[100%] /data/local/tmp/Smart AudioBook Player_3.1.3.apk
    pkg: /data/local/tmp/Smart AudioBook Player_3.1.3.apk
Failure [INSTALL_FAILED_INSUFFICIENT_STORAGE]

Po wejściu na urządzenie do /data/app było widać że apka jest zainstalowana. W końcowym rezultacie musiałem wykasować z dwóch katalogów pliki związane z tą apką:

  • /data/app/
  • /data/app-lib/
  • /data/data

Na razie podejrzewam problem z CM11 który niestety nie działa idealnie ale w porównaniu z CM12.1 i CM13 na Pentagramie zdecydowanie lepiej.

cd.

W końcowym rezultacie przywróciłem oryginalny ROM i na nim także miałem problem z zainstalowaniem apki, ale pomogła ręczna instalacja:

adb shell
...
pm install ADWLauncher\ EX_1.3.3.9.apk

cd.

Podobny przypadek wystąpi gdy mamy aplikacje przeniesione na kartę SD za pomocą np. Link2SD, które zostaną skasowane z karty. W systemie wówczas wiszę zepsute symlinki których standardowy instalator nie potrafi nadpisać, skasować.