paloma blog

NWエンジニアやってます。主に自宅環境のお遊びを書きます。Pythonもちょっと。タイトルは好きなカクテルから。

ログインシェルをzshに変えたらcronが動かなくなったので修正(しなくてもよかった)

家で使っているfireflyという家計簿アプリをのDBを日時でバックアップ取っているのですが 以前ログインシェルをbashからzshに変えたらバックアップ用のcronが動かなくなっていました。

成否のログを普段から確認していない問題は置いておいて動くように修正します。

正確には動いてはいるんだけど正常に取れていないという事象です。

環境

ubuntuのデスクトップ環境にLXDでコンテナサーバをいくつか動かして運用しています。
今回のfireflyも該当します。

    ~  screenfetch -n 
 masashi@PC-ubuntu
 OS: Ubuntu 22.04 jammy
 Kernel: x86_64 Linux 5.15.0-56-generic
 Uptime: 12d 6h 57m
 Packages: 3508
 Shell: zsh 5.8.1
 Resolution: 1280x1024
 DE: KDE 5.92.0 / Plasma 5.24.7
 WM: KWin
 GTK Theme: Breeze [GTK2/3]
 Icon Theme: breeze-dark
 Disk: 132G / 218G (64%)
 CPU: Intel Core i5-2400 @ 4x 3.4GHz [42.0°C]
 GPU: Mesa Intel(R) HD Graphics 2000 (SNB GT1)
 RAM: 8690MiB / 11690MiB

バックアップ用ディレクト

zshのターミナルそのまま貼ってますのでフォントの関係でプロンプトが文字化けしてます。(見にくくてすいません)

    ~  ls -l backup/firefly
合計 1912
-rw-rw-r-- 1 masashi masashi       0 12月 19 00:00 fireflyiii-db.sql
-rw-rw-r-- 1 masashi masashi       0 12月 19 00:00 fireflyiii-db.sql.bak
-rw-rw-r-- 1 masashi masashi  936880 11月  5 14:49 fireflyiii-db.sql.bak.20221105bak
-rw-r--r-- 1 masashi masashi     269 11月 20  2020 hosts
drwxr-xr-x 9 masashi masashi    4096 11月 16  2019 nginx

この通り0byteになっちゃってます。
日時でdumpのリダイレクトでフルバックアップ取ってるのですが、スクリプトが動かずに空ファイルで上書きしちゃってますね。
2年位運用しているので壊れた際のリストアができないのは困ります。

crontab

コメント部分抜いてますがcrontabはこんな感じ。
環境変数bashにしてしているからログインシェル変えても問題ないと思っていましたがオプションが悪さしてるのでしょうか。
動けばいいやで適当にコピって持ってきたのが悪かったです。
cronは環境変数を指定してあげないとだめと教わったので当時使っていたbash環境変数を呼べるように−lとか指定した記憶があります。
いろいろ試して不要なのも残っていますがPATHは指定しなくてもいいですね。

    ~  crontab -l
HOME=/home/masashi
PATH=/usr/bin:/bin:/home/masashi/bin
SHELL=/bin/bash
@daily bash -lc $HOME/bin/fireflybkup.sh

いきなり解決しました

執筆中に気づいたのですが呼び出し元のスクリプトファイルのコンテナ名が間違っていたためdumpできなかったというオチでした。
そういえば少し前に一回コンテナリストアして名前が変わったのですが、別ディレクトリのスクリプトのみ修正して終わってしまいました。
お恥ずかしい。
ログインシェル変更云々は全く関係なく、crontabも触らず、スクリプト内を修正して目的は完了です。


せっかくなのでbashオプションとかのおさらい

まあせっかくコマンドを調べる機会ができたのでこの際少しおさらいしましょう。
bashのmanを見たら以下のように説明されています。

  -c        If the -c option is present, then commands are read from the first non-option argument command_string.   If  there  are
            arguments  after  the  command_string, the first argument is assigned to $0 and any remaining arguments are assigned to
            the positional parameters.  The assignment to $0 sets the name of the shell, which is used in warning  and  error  mes‐
            sages.
  ...
  -l        Make bash act as if it had been invoked as a login shell (see INVOCATION below).
  • -c

通常だと1つ目の引数は$0で呼び出されるファイルに当てられますが、オプションつけることで1つ目の引数から渡せるということでしょうか。

zshのプロンプト見にくいのでbashで試してみます。

masashi@PC-ubuntu:~$ bash 'echo $0'
bash: echo $0: そのようなファイルやディレクトリはありません
masashi@PC-ubuntu:~$ bash -c 'echo $0'
bash

オプションがないとecho $0がファイル扱いになってしまいエラー吐いてますね。
cronはスクリプト呼んでるだけなのでこのオプションは無くてもいいかもしれません。

  • −l

ログインシェルとして呼び出すとなっています。

ログインシェルとは

字面だけで想像できますが、ログインした際に呼び出されるシェルですね。

リファレンスをみるとログインシェルとそうでないシェルで呼ばれるファイルが異なるようです。 (この辺は普段使ってる人には当たり前かもしれませんが)

Bash Startup Files (Bash Reference Manual)

ログインシェルは起動時にprofile系のファイルが読み込まれるようです。
対話型で使えるよう色々カスタムできるようたくさんファイルがあるんでしょうか。

  1. /etc/profile
  2. ~/.bash_profile
  3. ~/.bash_login
  4. ~/.profile

の順で読み込まれるらしい。

ログインシェルじゃない場合はrcファイル系。
子プロセスとかスクリプトで呼び出すシェルですね。
でも.bash_profileから.bashrcを呼び出すようになっているのでこのファイルは結局読まれます。

私の環境はubuntuデスクトップですが.bash_profileがありませんでした。
Xwindowありきの環境なので異なる部分が出てくるのは仕方ないですね。 私の環境では.profileが.bashrcを呼び出していました。

masashi@PC-ubuntu:~$ ls /etc/profile
/etc/profile
masashi@PC-ubuntu:~$ ls ./.bash*
./.bash_history  ./.bash_logout  ./.bashrc
masashi@PC-ubuntu:~$ ls .profile 
.profile

いまのログインシェルはzshです。
passwdファイル見てshellsの中から選ばれるてな感じですかね。

    ~  grep masashi /etc/passwd
masashi:x:1000:1000:masashi,,,:/home/masashi:/usr/bin/zsh
    ~  cat /etc/shells
# /etc/shells: valid login shells
/bin/sh
/bin/dash
/bin/bash
/bin/rbash
/usr/bin/tmux
/usr/bin/sh
/usr/bin/dash
/usr/bin/bash
/usr/bin/rbash
/bin/zsh
/usr/bin/zsh
    ~  echo $SHELL
/usr/bin/zsh

zshはどう呼ばれているのか

bashはわかったけどzshはどう呼ばれているのか?
ということで公式サイトを見てみます。

A User's Guide to the Z-Shell

$ZDOTDIRには何もなし。

    ~  echo $ZDOTDIR

/etc配下いにあるようなのですが、私の環境ではzshディレクトリにまとめられていました。
これはデスクトップ環境だからでしょうか。

    ~  ls /etc/z*
/etc/zsh_command_not_found

/etc/zsh:
newuser.zshrc.recommended  zlogin  zlogout  zprofile  zshenv  zshrc
    ~  ls .z*
.zcompdump  .zcompdump-PC-ubuntu-5.8.1  .zcompdump-PC-ubuntu-5.8.1.zwc  .zsh_history  .zshrc

ちなみにbashzshの起動後に一番最初にファイルを見に行く処理は誰がやっているんでしょうか?
文書には書かれていないところを見るとbash, zshの本体にコンパイルされてそうな感じがしますね。

まとめ

この辺の話は公式ドキュメントにもいろんな方の記事にも山のように公開されていますが、私でも自分なりに調べてスッキリできました。
よく検証する機器がデスクトップ環境という変則?な環境ではありますので公開されている記事の様にはカッチリはまらない場合もあります。
まあ、それをなんとかしていくのが楽しいんですけどね。