カテゴリー: テクノロジー

面倒な事をシステムでなんとかする

弊社では勤怠システムがWEBシステムになっているのですが、忘れることがあったのでえいやーでなんとかしてみました。

・WEB上に勤怠システムがある
・emailアドレスとパスワードでログインする必要がある
・システムではlaravelのtoken処理が使われているらしく、cookieとtokenも一致させなければいけない
・Macの起動と終了で勤務時間とみなす
・自分しか使わない前提でとりあえず動くもの

ひとまず出勤と退勤処理をするためのプログラムを作成
できあがったものが以下

#!/usr/bin/env bash

function usage {
  cat <<EOM
Usage: $(basename "$0") [OPTION]...
  -h Display help
  -e VALUE E-mail address
  -p VALUE Password
  -t VALUE Type(start, end)
EOM

  exit 2
}

API_HOST='kintai-system-no-host-dayo'
_EMAIL=''
_PASS=''
_TYPE='start'

while getopts ":e:p:t:h" optKey; do
  case "$optKey" in
    e)
      _EMAIL="${OPTARG}"
      ;;
    p)
      _PASS="${OPTARG}"
      ;;
    t)
      if [ "x${OPTARG}" = "xstart" ]; then
        _TYPE='start'
      elif [ "x${OPTARG}" = "xend" ]; then
        _TYPE='end'
      else
        echo "-t ${OPTARG}: unknown type."
        usage
      fi
      ;;
    '-h'|'--help'|* )
      usage
      ;;
  esac
done


if [ "x${_EMAIL}" = "x" ]; then
  read -p "E-mail address: " _EMAIL
fi

if [ "x${_PASS}" = "x" ]; then
  read -sp "Password: " _PASS
fi

# cookieの保存場所
tmpfile=$(mktemp)

# トークンの取得
_TOKEN=$(curl -s -c ${tmpfile} https://${API_HOST}/login | xmllint --html --xpath '//*form/input/@value' - | grep value= | sed 's/[^"]*"\([^"]*\)"[^"]*/\1/g')

# ログイン
curl -L -b ${tmpfile} -c ${tmpfile} -d "_token=${_TOKEN}&email=${_EMAIL}&password=${_PASS}" https://${API_HOST}/login

# 出勤もしくは退勤
curl -L -b ${tmpfile} -c ${tmpfile} -d "_token=${_TOKEN}" https://${API_HOST}/dashboard/${_TYPE}/

exit

適当なファイル名eiya-de-kintai.shとして保存し、実行権限をつけておきます。

$ chmod +x ~/eiya-de-kintai.sh



実行するには以下のようにします。
出勤

$ ~/eiya-de-kintai.sh -e email@example.splout.co.jp -p password-desu -t start


退勤

$ ~/eiya-de-kintai.sh -e email@example.splout.co.jp -p password-desu -t end

プログラムの内容は
・curlでログインページの取得を行い、一時ファイルにcookieを保存
 同時にレスポンスbodyからxpathでinput要素のvalueにあるtokenを取得
・取得したcookieとtokenとメールアドレス(-e)とパスワード(-p)をログインページへPOSTし、ログイン状態のcookieを保存
・出勤もしくは退勤(-tで指定)のエンドポイントへログイン状態のcookieを使いtokenをPOST

ログイン判定してないとかcookieが残骸として残る等かなり手を抜いているがひとまず気にしない。徐々に手を加えていく予定。

Macの起動と終了で処理を走らせるには、「Macの起動=アプリケーションの起動」、「終了=アプリケーションの終了」とみなすことにし、作成したシェルスクリプトを呼び出すApplescriptを作成しました。

Macに標準で入っているスクリプトエディタを起動

↑こんなアイコン

以下のコードを記述

on run
	do shell script "~/eiya-de-kintai.sh -e email@example.splout.co.jp -p password-desu -t start"
end run

on quit
	do shell script "~/eiya-de-kintai.sh -e email@example.splout.co.jp -p password-desu -t end"
	continue quit
end quit

これを
 ファイルフォーマット:アプリケーション
 オプション:ハンドラの実行後に終了しない。
で保存します。

出来上がったアプリケーションをMacのログイン時に実行されるようにします。
「システム環境設定」にある「ユーザとグループ」を開き
「ログイン項目」へ作成したアプリケーションの登録を行います。

以上でとりあえずのものが出来上がりました。

Macを起動し、ログインすると自動で出勤処理が行われます。
Macの終了時には自動で退勤処理が行われ、何も意識しなくても勤怠処理が行われるようになりました。


そう、エラーさえなければ・・・

アカウント情報を平文で書いているとかApplescript使うならシェルいらないのでは?とかエラー処理されていないとか、実用するにはまだまだまだまだ改善すべき箇所が多く残っていますが、ひとまず目標は達成しました。


SolrのReadOnlyモード

Solr 8.1から追加された機能にRead-Onlyモードがあります。SolrCloudでの運用時に利用できるモードです。リファレンスマニュアルの該当部分を翻訳してみました。

readOnly属性をtrueにセットするとコレクションはRead-Onlyモードに移行します。このモードではインデックスの更新リクエストは拒否されます。他のコレクションレベルのアクション(コレクションの追加/削除、レプリカの移動)はこのモードにおいても有効です。


(デフォルトの)read-writeモードからread-onlyモードへは以下の手順で移行されます。
・コレクション内のreadOnlyフラグが変更される
・すべての更新リクエストが403 FORBIDDENエラーで拒否される(継続中の長期実行リクエストは中止される)
・実行中の更新が強制的にコミットされる
(注意)大きなセグメントがバックグラウンドでマージされている最中であれば、この強制コミットは長時間に及ぶかもしれません。
・コレクションのRELOADアクションが実行される
readOnly属性が削除されるかfalseに設定されるかすると、更新リクエストが有効になりコレクションがリロードされます。

https://lucene.apache.org/solr/guide/8_2/collection-management.html#readonlymode

簡単な動作確認をしてみました。

$ curl 'http://localhost:8983/solr/admin/collections?action=CREATE&name=test_readonly&collection.configName=_default&numShards=1&wt=xml'

$ curl 'http://localhost:8983/solr/admin/collections?action=MODIFYCOLLECTION&collection=test_readonly&readOnly=true'
{
  "responseHeader":{
    "status":0,
    "QTime":476},
  "success":{
    "127.0.1.1:8983_solr":{
      "responseHeader":{
        "status":0,
        "QTime":350}}}}
$ bin/post -c test_readonly data.json 
SimplePostTool version 5.0.0
Posting files to [base] url http://localhost:8983/solr/test_readonly/update...
Entering auto mode. File endings considered are xml,json,jsonl,csv,pdf,doc,docx,ppt,pptx,xls,xlsx,odt,odp,ods,ott,otp,ots,rtf,htm,html,txt,log
POSTing file data.json (application/json) to [base]/json/docs
SimplePostTool: WARNING: Solr returned an error #403 (Forbidden) for url: http://localhost:8983/solr/test_readonly/update/json/docs
SimplePostTool: WARNING: Response: {
  "responseHeader":{
    "status":403,
    "QTime":207},
  "error":{
    "metadata":[
      "error-class","org.apache.solr.common.SolrException",
      "root-error-class","org.apache.solr.common.SolrException"],
    "msg":"Collection test_readonly is read-only.",
    "code":403}}
SimplePostTool: FATAL: Looks like Solr is secured and would not let us in. Try with another user in '-u' parameter

テスト用のコレクション(test_readonly)を作成し、MODIFYCOLLECTIONアクションでreadOnlyをtrueに設定してからドキュメントをポストするとリファレンスの説明通り403エラーになりました。

$ curl 'http://localhost:8983/solr/test_readonly/select?q=*%3A*&rows=1&start=0'
{
  "responseHeader":{
    "zkConnected":true,
    "status":0,
    "QTime":1,
    "params":{
      "q":"*:*",
      "start":"0",
      "rows":"1"}},
  "response":{"numFound":0,"start":0,"docs":[]
  }}

当然インデックスは空っぽのままです。

$ curl 'http://localhost:8983/solr/admin/collections?action=MODIFYCOLLECTION&collection=test_readonly&readOnly=false'
{
  "responseHeader":{
    "status":0,
    "QTime":466},
  "success":{
    "127.0.1.1:8983_solr":{
      "responseHeader":{
        "status":0,
        "QTime":344}}}}
	
$ bin/post -c test_readonly data.json 
SimplePostTool version 5.0.0
Posting files to [base] url http://localhost:8983/solr/test_readonly/update...
Entering auto mode. File endings considered are xml,json,jsonl,csv,pdf,doc,docx,ppt,pptx,xls,xlsx,odt,odp,ods,ott,otp,ots,rtf,htm,html,txt,log
POSTing file data.json (application/json) to [base]/json/docs
1 files indexed.
COMMITting Solr index changes to http://localhost:8983/solr/test_readonly/update...
Time spent: 0:00:01.420

次にMODIFYCOLLECTIONアクションでreadOnlyをfalseに戻してからドキュメントをポストしたところ、今度はエラー無しでアップデートできました。

$ curl 'http://localhost:8983/solr/test_readonly/select?q=*%3A*&rows=1&start=0'
{
  "responseHeader":{
    "zkConnected":true,
    "status":0,
    "QTime":0,
    "params":{
      "q":"*:*",
      "start":"0",
      "rows":"1"}},
  "response":{"numFound":9236,"start":0,"docs":[
      {
        "id":"158",
        "type":["官公庁"],
        "area":["住之江区"],
        "name":["軽自動車検査協会大阪主管事務所"],
        "address":["住之江区南港東3-4-62"],
        "_version_":1648645250184380416}]
  }}

クエリの結果からも、正しく更新できたことを確認できます。

ReadOnlyモードを使えば内容固定のインデックスを運用中に誤って更新してしまうことを防ぐことができて便利ですが、このモードはSolrCloudでのみ利用可能なので、その点は注意が必要です。


PHP LaravelとVue.jsでWebSocketしてみる

秋になると「紅葉見に行こうよ」と言いたくなるけど言う相手がいない。
マエダです。

気づいたら紅葉シーズン終わっていた。。

 

Laravelを触ってみてVue.jsってどんなもんだろうと調査してみる機会がありました。
他のメンバーがずっと以前の社内勉強会で発表してくれていた通りものすごく便利なことに気付かされました。。。
ただ長くjQueryに甘えていたのでこの場合はどうするの?がたくさん。

今回はWebSocketしてみました。

参考サイト

https://readouble.com/laravel/5.7/ja/broadcasting.html
https://qiita.com/zaburo/items/34289d4573f39113b25a

いきなり参考サイトですがこの手順通りに対応すれば動作確認できちゃいます。
ありがとうございました。

実行コマンド抜粋

npm install –save laravel-echo socket.io-client
composer require predis/predis
composer dump-autoload
npm install -g laravel-echo-server
laravel-echo-server init
laravel-echo-server start

URLをディレクトリ指定に

Nginx設定する。
sudo vi /etc/nginx/conf.d/app.conf

location /ws/{
    proxy_pass http://127.0.0.1:6001/;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header X-Forwarded-For $remote_addr;
}

jsのpathにディレクトリを指定する。
vi resources/js/bootstrap.js

import Echo from 'laravel-echo'
window.io = require('socket.io-client');
window.Echo = new Echo({
    broadcaster: 'socket.io',
    host: window.location.hostname,
    path: '/ws/socket.io',
});

window.Echo.channel('hoges')
    .listen('Hoge', (e) => {
        console.log(e);
    });

感想

ほんとに全然JavaScriptコードを書かずともLaravelでWebSocketを利用できることにシンプルに感動でした。
個人的にはメンバーに負けないようにVue.jsを理解を深めます!
「千里の道も一歩から」
https://jp.vuejs.org/


Microsoft Edge preview builds を触ってみる

Microsoft Edge(以下Edge)が Chromium を採用すると発表してから11ヵ月、もうすぐ1年になろうとしています。

そろそろベータ版も落ち着いたのではないかと思い、インストールから一通り触ってみた感想を書いてみます。

以下から Edge preview build のダウンロードができます。

Microsoft Edge Insider Channels
https://www.microsoftedgeinsider.com/ja-jp/download

お試しできるベータ版は3種類あり、今回は Dev ビルドをインストール。
この記事を書いている時点のバージョン情報は、「79.0.308.1 (公式ビルド) dev (64 ビット)」 となっています。

起動せよと呼ぶ声あり

起動時の画面がこちら。

Microsoft Edge preview build を開いた最初の画面

メニューはこんな感じです。

Microsoft Edge preview build のメニュー

現行版 Edge に比べてかなり Chrome に近い印象。

弊社サイトの Recruit ページを preview build と現行の Edge で表示させて並べてみました。

左が preview build, 右が現行版 Edge

CSS の解釈が違うのかベータ版だからなのか、ヘッダー(青い色の部分)の box-shadow が効いていません。

いくつかWebページを見て回りましたが、閲覧程度なら現行ブラウザとも遜色なく動作しているように見えます。
Edge Insider の「既知の問題」を見るとまだいくつかの問題は残っているようですが、随時修正されていくでしょう。

私は Chrome であり、Safari であり、Edge ではない

ユーザーエージェントは以下のようになっています。

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3943.0 Safari/537.36 Edg/79.0.308.1

Mozilla、AppleWebKit、Chrome と並んでいますが、Edge ではなく Edg となっています。
preview build であるため Edge にはまだ至っていないということなのか、このまま本採用されるのか。
開発者視点だと気になる点ではあります。

見よ、Chrome アドオンは共にある

新しい特徴として、Chrome アドオンが利用できるようになるとのことなので試してみました。

試してみるアドオンは Picture-in-Picture Extension (by Google)
https://chrome.google.com/webstore/detail/picture-in-picture-extens/hkgfoiooedgoejojocmhlaklaeopbecg

Chrome ウェブストアを Edge で開くと画面上部にメッセージが。

「他のストアからの拡張機能を許可する」というボタンをクリックすると、拡張機能のページに「Chrome に追加」のボタンが現れます。
押してみると何事もなく拡張機能に追加されました。

実際に試してみると、

PIPを有効にしたときの表示

Edge の外に PIP の小さなプレイヤーが表示され動画が再生されています。
ただ、試した限りでは残念ながら一時停止ボタンが機能しませんでした。

やがて Chrome になる?

ここまでをまとめると「Chrome によく似た何か」であり、それ以外の感想は特に出てきませんでした。
あまりに Chrome 然とし過ぎていて、どちらを使っているのか分からなくなります。

まずは基本機能の安定動作。
そこからの独自機能の実装という方針なのだと思います。

今後、実装予定の新機能が色々発表されていますし、edge://flags/ を開くと WebVR や WebXR Device API 等、気になる名称の機能が試験段階として無効化されていることが分かります。

試験段階の機能 Collections

そして、試験段階にある Internet Explorer モードが IE ユーザーに受け入れられるのかどうか。

正直にいえば、新しい Edge に一番期待しているポイントです。

IE がなくても Edge で問題ないということになれば、多くのWeb開発者の救済への大きな一歩となるかもしれません。

しかし、Chrome に似た何かで終わる可能性もあり…。

Microsoft 様におかれましてはどうかうまくやってくださいと強く祈るばかりです。


WSL上でSolrが動くかどうか試してみた

SolrはJavaで書かれているのでもちろんWindowsでも動くわけですが、ふとWSL上ではどうなのかが気になって試してみました。

まずは WSL 上でいつもの手順通りSolrを動かしてみます。ディストリビューションはUbuntu 18.04.2 LTSです。

Solrをダウンロードして展開

$ wget https://www-eu.apache.org/dist/lucene/solr/8.2.0/solr-8.2.0.tgz
tar zxf solr-8.2.0.tgz

起動

$ cd solr-8.2.0
$ bin/solr -e cloud

Welcome to the SolrCloud example!

This interactive session will help you launch a SolrCloud cluster on your local workstation.
To begin, how many Solr nodes would you like to run in your local cluster? (specify 1-4 nodes) [2]:
1
Ok, let's start up 1 Solr nodes for your example SolrCloud cluster.
Please enter the port for node1 [8983]:
8983
Creating Solr home directory solr-8.2.0/example/cloud/node1/solr

Starting up Solr on port 8983 using command:
"bin/solr" start -cloud -p 8983 -s "example/cloud/node1/solr"

*** [WARN] ***  Your Max Processes Limit is currently 7823.
 It should be set to 65000 to avoid operational disruption.
  If you no longer wish to see this warning, set SOLR_ULIMIT_CHECKS to false in your profile or solr.in.sh
  Waiting up to 180 seconds to see Solr running on port 8983 [|]  bin/solr: line 660:   177 Aborted                 (core dumped) nohup "$JAVA" "${SOLR_START_OPTS[@]}" $SOLR_ADDL_ARGS -Dsolr.log.muteconsole "-XX:OnOutOfMemoryError=$SOLR_TIP/bin/oom_solr.sh $SOLR_PORT $SOLR_LOGS_DIR" -jar start.jar\
 "${SOLR_JETTY_CONFIG[@]}" $SOLR_JETTY_ADDL_CONFIG > "$SOLR_LOGS_DIR/solr-$SOLR_PORT-console.log" 2>&1
   [\]  ^C
   ERROR: Failed to start Solr using command: "bin/solr" start -cloud -p 8983 -s "example/cloud/node1/solr" Exception : org.apache.commons.exec.ExecuteException: Process exited with an error: 130 (Exit value: 130)

エラー終了してしまいました。
実行ログを調べると、以下のようなJava VMレベルでのエラーが発生していました。

$ cat example/cloud/node1/logs/solr-8983-console.log
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (g1PageBasedVirtualSpace.cpp:49), pid=177, tid=185
#  guarantee(is_aligned(rs.base(), page_size)) failed: Reserved space base 0x00007f77bc420000 is not aligned to requested page size 2097152
#
# JRE version:  (11.0.4+11) (build )
# Java VM: OpenJDK 64-Bit Server VM (11.0.4+11-post-Ubuntu-1ubuntu218.04.3, mixed mode, aot, sharing, tiered, compressed oops, g1 gc, linux-amd64)
# Core dump will be written. Default location: core.177 (may not exist)
#
# An error report file with more information is saved as:
# solr-8.2.0/server/hs_err_pid177.log
#
# If you would like to submit a bug report, please visit:
#   https://bugs.launchpad.net/ubuntu/+source/openjdk-lts
#

WSLのバグレポートによるとJavaのプロセスで似たようなエラーが出ることはあるようで順次修正はされているものの、今回のエラーと同じものは見つかりませんでした。

Java VMの起動オプションを変更すれば起動するのではないかと考えて、まずはヒープサイズをいろいろ変えてみましたが駄目でした。
次にJMX関連のオプションを外してみたところ問題なく起動するようになりました。具体的には起動用のSolrスクリプトを以下のように変更しました。

--- solr.bak    2019-10-22 23:25:45.830541600 +0900
+++ solr        2019-10-27 19:05:03.758148800 +0900
@@ -1964,6 +1964,7 @@
 fi

 # These are useful for attaching remote profilers like VisualVM/JConsole
+ENABLE_REMOTE_JMX_OPTS=false
 if [ "$ENABLE_REMOTE_JMX_OPTS" == "true" ]; then

   if [ -z "$RMI_PORT" ]; then

開発中の動作確認ではWSL側でSolrが動かせた方が都合が良い場合もあるので、謎のエラーを回避する方法を見つけることができて良かったです。