yn2011's blog

技術メモ

シェルスクリプトの出力を画面に表示しつつファイル出力する方法について

環境

ターミナル上の作業ログを取りたい場合

  • scriptコマンドを使うとターミナル上の操作と出力を全てファイルに記録できる
$ script
Script started, output file is typescript
$ echo hoge
hoge
$ ls hoge
ls: cannot access 'hoge': No such file or directory
$ exit
// typescript
Script started on Sun Dec  2 19:15:10 2018
bash-4.4$ echo hoge
hoge
bash-4.4$ ls hoge
ls: cannot access 'hoge': No such file or directory
bash-4.4$ exit
exit

Script done on Sun Dec  2 19:15:45 2018

実行するシェルスクリプトのログを画面に表示しつつファイル出力したい場合

exec 1> >(tee -a stdout.log)
exec 2> >(tee -a stderr.log)

# 処理
echo hoge
  • なる...ほど?
  • シェルスクリプトに慣れ親しんでいないと分かりにくい(少なくとも自分は理解できなかった)
  • 分解して考えてみる

リダイレクト

  • 始めにリダイレクトの概念を知っている必要がある

リダイレクトは標準入出力の入力元、出力先を置き換える機能のこと

[三宅 英明 (2017) . 新しいシェルプログラミングの教科書 SBクリエイティブ P115より引用]

  • 例えばecho hoge 1> hoge.logは標準出力をhoge.logにリダイレクトする
  • 1はファイルディスクリプタの番号
  • 1>を省略すると>になるのでecho hoge > hoge.logでも良い

execコマンド

  • 続いてexec

execに指定したコマンドを実行する。このコマンドを実行する際に,新しいプロセスを作成せずに,現在のジョブと置き換えて実行される。...また,何もコマンドを指定せずにリダイレクトを利用すると,現在のシェルのリダイレクトを切り替えられる。

【 exec 】 現行のジョブに置き換えてコマンドを続行する | 日経 xTECH(クロステック)より引用

  • ここではコマンドを指定していないのでシェルのリダイレクトを切り替えている

プロセス置換

  • <(command)>(command)の2つがある

<(command)

  • <(command)は、プロセス置換によって割り当てられたファイルにcommandの標準出力を出力
  • シェル芸でも時々使う
$ echo <(echo test)
/dev/fd/63

$ cat <(echo test)
test

>(command)

  • >(command)は、プロセス置換によって割り当てられたファイルの内容を標準入力としてcommandを実行
    • execと組み合わせることが多い模様
    • 今回はシェルの出力が、一時的に割り当てられたファイルへリダイレクトされ、それを標準入力としてコマンドが実行される

teeコマンド

  • 最後にtee

    tee(ティー)はUnixのコマンドの一つ。 コマンドの標準出力 (stdout)を他のファイルにコピーできる機能を提供する。

tee (UNIX) - Wikipediaより引用

  • 標準出力しつつファイルにも出力する
  • 処理の流れがT字型のイメージ
  • -aはファイルに追記のオプション
$ echo hoge | tee hoge.log
hoge

$ cat hoge.log
hoge

これらを踏まえて

  • もう1度見てみる
exec 1> >(tee -a stdout.log)
exec 2> >(tee -a stderr.log)
  • 現在のシェルの標準出力と標準エラー出力をそれぞれteeの標準入力にすることで画面に出力しつつファイルへの記録を実現している
  • 処理の意味が理解できた!(と思う)

最後に


  1. 元記事のexec 2> >(tee -a stderr.log >&2)>&2はどうして必要なのかよく分からなかった。知っている方いたら教えてください

varなしの宣言(初期化)が関数スコープになる場合について

JavaScriptの変数の宣言文について、何となく気になったこと。

  • varなしの宣言で初期化された変数はグローバルスコープ
    • これはよく知られている仕様
(function() {
  foo = 1;
})();
console.log(foo); // 1
  • varなしの宣言で初期化された(ように見える)変数でも、関数の引数なら関数スコープ
    • 関数スコープ内に引数の変数が予め宣言されているような動作っぽい
(function(foo) {
  foo = 0;
})(1);
console.log(foo); // Uncaught ReferenceError: foo is not defined
  • varなしの宣言で初期化=グローバルスコープに囚われていたので「あれ?」となった

引数に再代入する処理を書くとコードが分かりにくくなると思うので、あまり上のように書くことはないけど...

document.referrerでiframeからクロスドメインの親ページのURLを取得できる理由について

気になったので調べた内容をまとめた。

iframeからクロスドメインの親ページのURLを取得する

  • document.referrerでできる(ほとんどのブラウザで動作するっぽい。Chrome, Firefox, Safari, Edge, IE11の最新版はどれも動いた)
  • 同一ドメインの場合はdocument.location.hrefでもいける
  • この違いは何なのか気になったので調べた

そもそもdocument.referrerは何を取得しているのか

  • document.referrerはHTMLファイルの取得のために発行したHTTPリクエストのHTTPリファラを取得する

HTTPリファラとは何か

HTTPリファラ(英: HTTP referer)あるいは単にリファラは、HTTPヘッダの1つで、インターネット上の1つのウェブページまたはリソースから見て、それにリンクしているウェブページやリソースのアドレスを指す。

HTTPリファラ - Wikipediaより引用

  • このブログを開いた際に発行されるHTTPリクエストのヘッダーにもHTTPリファラが含まれている

f:id:pokuwagata:20181126001218p:plain

なぜdocument.referrerでiframeの親ページのURLを取得できるのか

  • 親ページからiframeの内容を取得するために発行されるHTTPリクエストのヘッダーにHTTPリファラが含まれている場合が多いから(もしHTTPリファラが含まれていない場合は取得できない)
  • 例えばiframeのタグは下記のようになるが、src属性にURLが指定されているのでページ描画時にリソース読み込みの対象になる

<iframe src="https://..."></iframe>

document.referrerにクロスドメイン制約がないのはなぜか

  • document.referrerは値を書き換えてもHTTPリクエストは発行しない(既に発行済のHTTPリクエストのヘッダー情報を参照しているだけなので)
    • そもそもJavaScriptからは書き換えられない

document.location.hrefにクロスドメイン制約があるのはなぜか

  • document.location.hrefで取得されるURLと実行時のURLのドメインが異なるとクロスドメイン制約に当たる
  • そもそもクロスドメイン制約は、悪意あるJavaScriptが異なるドメインに対してリクエストを発行することを防ぐためにある
  • document.location.hrefの値を書き換えると任意のURLに対してHTTPリクエスト(GET)を発行出来てしまうのでクロスドメインの場合は参照不可の仕様と思われる

HTTPリファラを制限できないか

  • 外部に公開したくないURLからHTTPリクエストを発行する場合等、HTTPリファラを制限したいことがある
  • ページ全体、リソース毎に柔軟に設定できる。詳細は下記にまとめられている。

所感

まだまだHTTPリクエストのヘッダーは分からない属性が多いので1つずつ理解していきたい

コンテナを中心にDocker、Herokuの基本概念を整理する

Docker、Herokuについてコンテナを軸に基本的な言葉の意味や概念を整理してみたいなあと思ったので書いた。引用中心なので詳細は各ページを参照ください。

そもそもコンテナとは何か?

コンテナは、リソースが分離されたプロセス内で、アプリケーションおよびその依存関係を実行できる、オペレーティングシステムの仮想化の 1 つの方法です。

コンテナとは – アマゾン ウェブ サービス (AWS)より引用

  • OSのプロセスとスレッドの違いが曖昧な方はこちらも スレッド (コンピュータ) - Wikipedia
    • ちなみに並行(コンカレント)と並列(パラレル)の違いについては...(略)

コンテナ vs 仮想マシン

仮想マシン (VM) はサーバーハードウェアを仮想化し (直接管理する必要をなくす)、コンテナはサーバーのオペレーティングシステムを仮想化します。

f:id:pokuwagata:20181121003636p:plain

  • 上記の図はHypervisor型仮想環境上を例にコンテナと仮想マシンの違いを説明している(と思われる、特に明文化されていないので自分の解釈)
  • 仮想マシンは上図のGuest OSからAppまでのこと
    • 図にはないけど仮想マシンという言葉はハードウェアの仮想化も含むと思う
  • コンテナは(Guest OSにインストールされた)エンジン上のBins/LibsからAppまでのこと(=仮想化されたOSを含むユーザ定義の実行環境)

コンテナとは – アマゾン ウェブ サービス (AWS)Docker とは | AWSより引用

コンテナの利点

  • 仮想マシンに比べて軽量
    • 軽量・効率的な理由は、例えばハードウェアの仮想化不要、各コンテナはプロセスとして起動等が挙げられる
  • アプリケーションや開発環境のポータビリティ高
    • 配布可能、同一環境の再現が容易

DockerはコンテナのOS

Docker はコンテナに対するオペレーティングシステムです。仮想マシンがサーバーハードウェアを仮想化 (直接管理する必要をなくす) ように、コンテナはサーバーのオペレーティングシステムを仮想化します。Docker は各サーバーにインストールされ、シンプルなコマンドを使ってコンテナを構築、開始、停止できます。

Docker とは | AWSより引用

コンテナのオーケストレーション

クラスタリング

そこで、多数のサーバーを組み合わせることがよく行われています。このような仕組みのことを、「クラスタリング」(Clustering)と呼びます。これにより、高い負荷がかかる処理を、複数のサーバーに分散することができ、システム全体の性能を高めることができます。また、多数のサーバーで同じ処理を実行できるようにしておけば、その中の1台のサーバーが故障などで停止したとしても、残りのサーバーで処理を続行することができ、システムを止めずに運用することができます。

https://blog.arena.ne.jp/docker/1868より引用

スケジューリング

  • いつ、どのコンテナ作成・実行を行うか

Kubernetesはコンテナのオーケストレーションシステム

Kubernetes(クーベネティス/クーベルネイテス、よくK8sと略記される)は、コンテナ化したアプリケーションのデプロイ、スケーリング、および管理を行うための、オープンソースのコンテナオーケストレーションシステムである。

Kubernetes - Wikipediaより引用

Herokuはコンテナベースのクラウドプラットフォーム

Heroku は、マネージドコンテナシステムをベースとし、最新鋭のアプリのデプロイや実行に必要なデータサービスと強力なエコシステムを備えたクラウドプラットフォームです。

Heroku Platform as a Service & Data Services | Heroku | Herokuより引用

Herokuで使用されるコンテナdyno

Heroku で使用されるコンテナは「dyno」と呼ばれます。dyno はユーザーが指定したコマンドにもとづいてコードを実行するように設計された Linux コンテナであり、それぞれが相互に隔離された状態で仮想化されています。

Heroku Dynos | Herokuより引用

HerokuでDockerを動かす?

感想

この手のサービスはチュートリアル通りに動かすのは簡単だが、そこから少しでも外れたことをしようとすると大変になりがち。そもそも自分がやろうとしていることとサービスの目的や方向性が合致していない場合もあり、試行錯誤する時間が無駄になることもある。サービスのベースになっている技術からサッと筋の良し悪しを判断できるといいですね...

職務経歴書を書いて公開した

転職活動しているわけではないけど書いてみたくなったので書いた。書いたものはこちら→職務経歴書

書いた理由

  • これまでの経験を振り返って自分の立ち位置を明確にしたかった(たいして長いキャリアでもないが)
  • オンライン(TwitterやBlog)で自分を知った人への自己開示
    • 自分に興味を持ってもらえると嬉しい
    • プロフィールページ的役割

書くときに参考にした情報

書くときに意識したこと

  • とにかくシンプルにする

    • 言語や経験等は細かく書きたくなってしまいがちなので選択的に書いた
      • 例えば自分の場合だと大学で1,2年間ぐらいCやJavaPythonやってたけど大して得意というほどでもないし、スキルとして強く主張したいわけでもないので省略した
    • 文は1単語でも短くできるように意識を払う
  • 少しエモさを含める

    • キャリアが浅いと職務経験の列挙だけでは情報不足
      • 自分は何ができて、何がしたい人なのか、どんなキャリアを目指しているのか伝わらない
    • 自分が大事にしていることや、挑戦したいことも軽く書いておく(自分はあまり採用を強く意識してないので現状実践できてないけど)
    • 読んでいる人も退屈しないかも
  • 日本語にする

    • Githubで公開するし、意識が高まって英語で書いてみたくもなりがち
    • でも実際のところ読者のほとんどは日本語ネイティブだと思うので英語で書く意味がない(英語版もあるに越したことはないと思う)

誰でもアクセス可能であるということ

  • 職務経歴書の性質上、分かる人が見れば個人を特定可能なレベルの情報公開になる
    • でも、(ある程度内容を選んだ)職務経歴書を公開できないのは何か自分のキャリアに負い目を感じていたりオンライン上の人格と現実の個人を結び付けられると困るような何かをしているからでは?とも思っている
  • 直近の職歴の部分を細かく書きすぎると自分の思いもよらないところで迷惑だったりするかもしれないのでそこは注意
    • 社名については、今回自分の職務経歴書を書くにあたり公開されている職務経歴書を10数点以上確認したけど明記している例が多かった(ので自分も書いておいた)

技術メモもそうだけど、公開可能な形にアウトプットしておくことで客観的に見れる部分が多くなると思う。アウトプット大事。

Appleサインイン画面で403エラーが発生したのでブラウザのCookieを削除したらエラーが解消した

環境

事象

原因

  • 軽く調べてみたけどCookieと403エラーの関係はよく分からなかった
    • セキュリティ的な問題なのかも
  • 別にAppleWebサービス特有の事象というわけではないっぽい

kakasiとnkf

【問題と解答】jus共催 第37回シェル芸bot生きてるかどうか分からないけどシェル芸bot向けシェル芸勉強会 | 上田ブログのQ7を読んでいていて、kakasiは入力と出力の文字コードを指定できるのかーと思ったので書いた。

環境

nkfによる変換は必要?

  • kakasiの利用例をみると下記のようにnkfを前処理と後処理に使っているものが多い
  • nkfEUC-JPに変換した後にkakasiを通して平仮名に変換しUTF-8に戻して標準出力する場合はこんな感じ
$ echo 漢字 | nkf -e | kakasi -JH | nkf -w
かんじ
  • kakasiのオプションで入力の文字コードを指定する場合はnkfは不要になる
  • シンプルで良い
$ echo 漢字 | kakasi -i utf-8 -JH
かんじ
$ echo 漢字 | kakasi -i utf-8 -o jis -JH
$+$s$8

kakasiのオプション

  • ではnkfを使う例が多い(気がする)のはなぜなのか?
    • オプションがあまり知られていない?
  • manコマンドで詳細を確認する
  • KANJI CODING CONVERSIONより

    Unfortunately, several coding systems are used in Japan and JIS x0208 standard are changed at 1983. Therefore, KAKASI can automatically distinguish the coding system and coding revision and then use the same output coding system if the document does not include JIS x0201 KATAKANA. If JIS x0201 KATAKANA is included or you wish to change kanji coding system, you may use the next options.

  • 上記によるとJIS x0201のカタカナ(JIS x0208から見た半角カナ)が含まれていない限りは自動的に文字コードの識別が可能とのこと

    • しかし自分の環境ではあまり上手く識別されなかった
    • kakasi - manned.orgより引用

      • もしも指定されない場合には入力から判断しようとします。 KAKASIは入力をためこんで統計的に処理する方法がとれないので、 最初の漢字らしい文字をもって判断します。

  • 自動的に識別した場合は入力の文字コードで出力する

  • もちろん明示的にオプションで入出力の文字コードを指定することも可能