singularityを使ったLaTeXのビルド環境を学科GitLabに構築した

自分がubuntuに作業環境を変えたこともあるのだけれど、最近の新入生のMacBookの容量が125GBとMacTeXをいれるには心もとない状態だったので、GitLabのCI/CDでLaTeXのビルドをしようとしていた。

paperist/alpine-texlive-jaにパッチをあたものを使っていたのだけれど、GitLab CIでLaTeXをビルドしようとする場合、 生成したPDFがroot権限になってしまうという問題がある。

su-execとか使ってどうにかしようとしたのだけど、ちょっとめんどくさいしidをdocker runの時に渡さないと行けないのが解りやすくないので厳しい気持ちになっていた。

学科システムでは別のコンテナランタイムとしてsingularityを使っている。

singularityはなんとuid/gidが実行時ユーザーと同じ状態で実行されたり、自動でホームディレクトリがマウントされるなど、今回のようなlatexのコマンドをコンテナから使う環境としてはぴったし。 ということでDockerfileをもとにsingularityのdefファイルを作った。

defファイル

gitlab.ie.u-ryukyu.ac.jp

dockerからの変更点

基本的にDocker時代のものをそのまま利用すれば良いのだけれど、singularityならではの変更点がいくつかある。

  • singularityの場合/tmpにファイルを書き出してbuildするのはNG

    • /tmpはホストの/tmpとマウントされてしまう
    • 今回はLaTeXのインストールスクリプトを置く場所を/latex以下にすることで回避
  • %environmentはビルド時に解決されない

    • PATHをいじってビルドしようとする場合は問題が生じる
    • %postの中で明示的にexportすることで解決

他にはepsを含めたいのでgostscriptを、makeしたいのでmakeをインストールするようにしている。 あまり関係ないが、CTANもミラーサーバーに向けているなどの違いがある。

あとはsingularity run latex.sif uplatex hoge.texとかしたいので、%runscriptで引数をexecするように書く。

%runscript
  exec "$@"

ビルド

singularity build --fakeroot latex.sif latex.def

使い方

sungularity runでも良いのだけれど、sifファイルにはシェバングが埋め込まれていて、自動でsingularity run出来る。

なのでこんな感じで使える。

$latex.sif latexmk
$latex.sif make

gitlab ciの設定は別のエントリで

合わせて読みたい

ie.u-ryukyu.ac.jp

ubuntuでdf: /run/user/1000/doc: Operation not permitted とか怒られる

なんかdfするとdf: /run/user/1000/doc: Operation not permittedとか怒られる。

$ df       
df: /run/user/1000/doc: Operation not permitted
Filesystem     1K-blocks      Used Available Use% Mounted on
tmpfs            3214652      2404   3212248   1% /run
/dev/nvme0n1p2 959863856 160878272 750157376  18% /
tmpfs           16073244    116640  15956604   1% /dev/shm
tmpfs               5120         4      5116   1% /run/lock
tmpfs               4096         0      4096   0% /sys/fs/cgroup
/dev/nvme0n1p1    523248      7984    515264   2% /boot/efi
tmpfs            3214648       136   3214512   1% /run/user/1000

ググったとことdfのバグとか、flatpackのバグとか主張しているサイトが見つかったが、ubuntuの場合はxdg-document-portalを止めればいいらしい。

$ systemctl --user stop xdg-document-portal.service

問題なさそう。ちなみにディレクトリは消せなかった。

$ df
Filesystem     1K-blocks      Used Available Use% Mounted on
tmpfs            3214652      2416   3212236   1% /run
/dev/nvme0n1p2 959863856 160933308 750102340  18% /
tmpfs           16073244    377076  15696168   3% /dev/shm
tmpfs               5120         4      5116   1% /run/lock
tmpfs               4096         0      4096   0% /sys/fs/cgroup
/dev/nvme0n1p1    523248      7984    515264   2% /boot/efi
tmpfs            3214648       140   3214508   1% /run/user/1000

askubuntu.com

Ubuntuのdiscordアプリのフォントを変える

Ubuntuのdiscrodのフォントが奥ゆかしいことになっており、変更してみた。

BetterDiscordのインストール

Discordアプリをいい感じに編集できるBetterDiscordをインストールする。 linuxの場合はgistを読んでコマンドを打つ。

gist.github.com

$curl -O https://raw.githubusercontent.com/bb010g/betterdiscordctl/master/betterdiscordctl
$chmod +x betterdiscordctl
$sudo mv betterdiscordctl /usr/local/bin

discord自体はsnapでいれているので、snapオプションをつけてinstallする

$betterdiscordctl install --snap

フォントの変更

ユーザー設定-> Custom CSSから

* { font-family: "Noto Sans CJK JP" !important;
-webkit-font-smoothing: subpixel-antialiased;
}

参考資料

ch.nicovideo.jp

Ubuntuで撮影したスクショを日付順に整理するコマンドかいた

自分しか使わなさそうツールです。

Ubuntuではスクショを取ると、~/PicturesScreenshot from 2021-01-03 08-28-12.pngみたいな名前でスクショが保存されます。 放置しているとスクショが溜まって大変なので、年/月/日でディレクトリを切って、そこに移動させるスクリプトを書きました。 Perlでファイル操作するときは最近はPath::Tinyが以上に便利でいいですね。

#!/usr/bin/env perl
use strict;
use warnings;
use Path::Tiny;

my $pictures_path = shift // $ENV{"HOME"}."/Pictures";
my $pictures_dir = path($pictures_path);

my $screenshot_reg = qr/Screenshot from (\d{4})-(\d{2})-(\d{2}) (\d{2}-\d{2}-\d{2}\.\w+)/;
#Screenshot from 2021-01-03 08-28-12.png

for my $file ($pictures_dir->children(qr/Screenshot from/)) {
  if ($file !~ /$screenshot_reg/) {
    print "[ERRPR] failed parse", $file->[0],"\n";
  }

  my $year         = $1; #2021
  my $month        = $2; #01
  my $day          = $3; #03
  my $picture_name = $4; #08-28-12.png

  my $new_picture = path("$pictures_dir/Screenshot/$year/$month/$day/$picture_name");
  $new_picture->touchpath;
  $file->move($new_picture);
}

おそるべきプログラミング入門サイトExercismをやってみた

Twitterで見かけたのでやってみました。

exercism.io

触った感じだと、Progate的なwebブラウザでプログラミングするタイプではなくて、truckに近く、コマンド経由でローカルに課題をダウンロードし、コマンド経由で回答を提出するという感じのプログラミング入門サイトです。これで無料なのはすごい気がする。

会員登録はGitHubAuthが使えるのでそれでしました。 特に何も打つ必要がないので便利。

課題のダウンロード/提出にはexercismというコマンド経由で行う必要があり、今はubuntuユーザーなのでsnapでinstallしました。

$sudo snap install exercism

exercismをインストールしたら、トークンを設定する必要がある。

$exercism configure --token=<トークンを貼る>

ちなみにいきなり動かそうとするとエラーがでて、トークンを発行するURLが案内される。

$ exercism download --exercise=hello-world --track=raku
Error:

    Welcome to Exercism!

    To get started, you need to configure the tool with your API token.
    Find your token at

        https://exercism.io/my/settings

    Then run the configure command:

        /snap/exercism/5/exercism configure --token=YOUR_TOKEN

exercismは他にいろいろ設定できるみたいで、作業用ディレクトリも設定可能。 初期設定だと$HOME/snap以下が作業ディレクトリとなってしまうので、今回は自分で作ったworkspaceディレクトリを設定した。 自分で作ったworkspaceにcdした状態で次のコマンドを実行。

$exercism configure -w=$PWD

これで初期設定が終わるので、あとは問題で指定されているコマンドを打って課題をローカルにダウンロードする。 課題はいろいろな言語があるのだけれど、今回はRaku(Perl6)を選んでみました。

$exercism download --exercise=hello-world --track=raku

今回はrakuの下にhello-worldというディレクトリが作られていました。

$ pwd
/home/anatofuz/workspace/exercism/raku/hello-world
$ls
HelloWorld.rakumod  hello-world.rakutest  README.md

あとはここで課題に応じてプログラムをしたり、テストを動かしたりすれば良さそう。 僕はRakuだったので、とりあえずRakuでテストをいい感じに動かすprove6をインストールした。

$zef install App::Prove6

テストを確認するとこんな感じ。Hello, World!と返すhello関数を作ればいい。

+kajika+anatofuz$ cat hello-world.rakutest
#!/usr/bin/env raku
use Test;
use lib $?FILE.IO.dirname; #`[Look for the module inside the same directory as this test file.]
use HelloWorld;
plan 1; #`[This is how many tests we expect to run.]

# Run the 'is' subroutine from the 'Test' module, with three arguments.
is(
  hello,           # Run the 'hello' subroutine, which is imported from your module.
  'Hello, World!', # The expected result to compare with 'hello'.
  'Say Hi!'        # The test description.
);

ということでHello.modを編集

$ cat HelloWorld.rakumod
#`(
  This is a 'stub' file. It's a little start on your solution.
  It is not a complete solution though; you will have to write some code.
)
unit module HelloWorld;

sub hello is export {
    return "Hello, World!";
}

prove6でテストを実行。通ってる。

+kajika+anatofuz$ prove6 .
hello-world.rakutest .. ok
All tests successful.
Files=1, Tests=1,  0 wallclock secs
Result: PASS

ここまで出来ると課題提出が可能。submitで提出。

$exercism submit ./HelloWorld.rakumod

通っているとターミナル側でURLが生成されるので、それを開いて答えがあってるかの確認とかを行う。 答えがあってる場合は、自分の回答を公開するかどうかとかを聞かれるのでそのあたりに答えると次の課題がアンロックされる感じでした。

所感

1問くらいしか動かしてないですが、就活でのコーディング面接の雰囲気を知るとかの意味でも結構おすすめです。 全部英語なので読むのは大変かもしれませんが、わかりやすい英語ですし、テストコード見ればだいたい雰囲気がわかる感じなので、暇なときにやってみましょう。

snapでVLCをインストールする

ubuntuでよく使われているパッケージツールのsnapを使って動画再生ソフトのVLCをインストールする。

snapはGUIも持っていて「ubunntu software」からアクセスすることが出来る。 雑にVLCで検索すると、なんか2つ出てくる。

f:id:anatofuz:20210107173322p:plain

違いは何かというと、下のopen sorceとか書かれていないVLCはinstallして使うと、音声は流れるけど動画が流れないなどの仕様になっている。 あとファイルアクセスのAPIGNOMEのものを使ってなさそうなので、上にでてきた方を入れると使用可能。

使ってみたところwindows/macとほぼ同じ雰囲気で使えたので良かった。ubuntuにはもともとビデオアプリが入っているのだけれど、どっちがいいのかはまだわからない。

hg webを開くコマンドのlinux対応

ubutu引っ越しシリーズ。 個人的に使っていたツール周りをlinuxに移植している。

anatofuz.hatenablog.com

このエントリで紹介していた個人ツールのhg-browselinuxに対応させた。 といっても、macOSopenコマンドをxdg-openに書き換えればいいだけなので割と簡単。

実際に書き換えた結果はこんな感じ。

#!/usr/bin/env perl
use strict;
use warnings;

# hg config経由でhgrcにかかれているpush先を確認する
my $push_path = `hg config paths.default`;

if ($?){
    print "[eror] failed exec hg config paths.default";
    exit 1;
}

my $open_cmd = $^O eq 'darwin' ? "open" : "xdg-open"; #linux open cmd is xdg-open

# 無かったら特に何もしない
exit 1 unless ($push_path);


# yomitanはパスで開けないので別枠
my $url;

if ($push_path =~ /(yomitan)|(chatan)/){
    $url = yomitan($push_path);
} elsif ($push_path =~ /firefly/){
    $url = firefly($push_path);
} else {
  if ( $push_path =~ m[(https?|ssh)://(\w+@)?(.*)]){
      $url = "http://$3";
  }
  die 'invalid url';
}

`$open_cmd $url`;


sub yomitan {
    my $input  = shift;
    my $http_domain = 'https://ie.u-ryukyu.ac.jp/hg/';
    my $url;

    if ($input =~ m[.*//home/hg/y(\d+)(.+)]){
        $url = $http_domain . "y$1$2";
    }
    return $url;
}

sub firefly {
    my $input  = shift;
    my $http_domain = 'http://www.cr.ie.u-ryukyu.ac.jp/';
    my $url;
    if (($input =~ m[.*?firefly.cr.ie.u-ryukyu.ac.jp/(.*)] )||($input =~  m[.*firefly/(.*)])){
        $url = $http_domain.$1;
    }
    return $url;
}

まぁほとんど変化はないのだけど、今までIPC::Run3を使っていた箇所をPerlのバッククォート演算子(`)を使うように変更した。 これに伴ってコアモジュールだけで済むようになったので便利。

linuxの対応は、Perlの場合特殊変数$^OでOSの名前が取れるので、darwin(macOS)かそうでないかで処理を分けている。 まぁこれにwindows対応まで入れるとif-elsifを書かないといけなさそうだけど、まぁしばらくwindows上で生で動かす予定はないので良さそう