SI におけるパラメータシートとは何か

パラメータシートという言葉をよく聞くが、いまいち理解してなかった。また自動化や IaC が当たり前な昨今でも「パラメータシートは撲滅できない(すべきではない)」とする意見が多く、なぜなのかがわからなかった。

このあたりの疑問を解消するべく、会社で尋ねたり資料漁ったりググったりしたので、まとめる。

パラメータシートとは

パラメータシートとは SI(の環境構築)における「この機器の、ここの値は、これこれの理由でこれにする」を集めたシートのこと。

大まかなフロー

  • 設計
    • パラメータシートをつくる
    • 1: 必要な設定を洗い出す
    • 2: 洗い出した設定の設定値を確定する
    • 3: パラメータシートに記入する
  • 手順書作成
    • 構築手順やテスト手順をつくる
  • 環境構築
    • パラメータシート(と手順)を見ながら手作業で設定を変えていく
    • 環境は本番かつ高セキュリティで触れるチャンスは少ない傾向
  • テスト
    • ちゃんと設定できてるか設定値を見たり軽く動かしたりする
    • 大体テスト仕様書に従ってやる

運用の現実

パラメータシートの書き方

  • Excel で列挙ゲー
  • フォーマットは各社各チームガラパゴス
  • 各社各チームの既存フォーマットを使い回す

手順書の作り方

  • つくらない派
    • 「パラメータシート見たらわかるやろ」
    • 構築時の主観が強くなるため、あまりない(と思う)
  • パラメータシートとは別につくる派
  • パラメータシート中に手順も書く派

環境構築時の制約

  • お客さん環境なので気軽に触れない
  • お客さん環境なので気軽に改善を試せない
  • 自席未満の劣悪な環境 + 制限時間や立ち会い付のプレッシャー

作業者のリテラシー

  • 可読性や保守性といった概念を知らない
  • バージョン管理を知らない
  • 自動化を知らない

近年の自動化や IaC ブームに対して、SIer は?

  • パラメータシートは撲滅できないという認識
    • 手順書作成と環境構築 → IaC できる
    • テスト → 自動テストできる
    • パラメータシート → 無理くね?

なぜパラメータシートを撲滅できないのか?

Ans: そもそも自動化や IaC のスキル・やる気・機会が無い から。

ただし真面目に検討している事例として NTT データの SlideShare があった。これによると、パラメータシート(的な設定マスタ)の撲滅は難しい との結論。

  • そもそも本番環境には気軽にアクセスできないので「本番環境の設定がどうなってるか」は別途手元で持っておくしかない
    • この時点で二重管理確定
  • 「Excel パラメータシート見て手作業で頑張れ」は撲滅できうる
    • IaC と自動化で構築とテストは自動化できる
    • 設定マスタはコード
    • コードだと読みづらいので、コードから「見やすいビュー」を生成して、普段はこのビューを見る

もっと撲滅するために

では上記の NTT データの例以上に撲滅をすすめることはできるだろうか。机上だがアイデアを。

環境情報取得ツールで二重管理を廃止する

仮に本番環境から設定情報すべてを吸い出すツールがあるなら、(吸い出したデータをこちら側で持っておくことは必要だが)二重管理は廃止できる。なぜなら、本番環境から吸い出せば常に寸分たがわぬ最新データが手に入るから。

もっとも実現は簡単ではない。以下が必要となる。

  • 本番環境(に存在する設定対象)すべてから設定情報をプログラマブルに吸い出せること
    • 機器・ネットワーク・ルール次第では仕様的に無理なことも……
  • 吸い出しは定期的に行い、吸い出したデータはバージョン管理すること
  • 設定の根拠や背景を記したドキュメントを整備し、漏れなくメンテすること
    • さすがに本番環境に埋め込むのは無理だろう
    • そもそもプログラミングでも内部的な話はコメントではなく外(別ドキュメント)に出す

……無理そう。

パラメータシート改めパラメータコードを導入する

SIer には以下が当てはまると思ってる。

  • 「コードは読みにくい」という思い込みを持っている
  • リーダブルなコードを書くという心がけがない(or リーダブルという概念を知らない)
  • スラスラ読めるレベルにまで(コードを記述した)言語に習熟していない or 機会がない or やる気がない

これらすべてを解消すれば、シート(リテラシーが無くても読めるけど連携とメンテがクソな表文書)を使わずともコードだけでパラメータを記述できるはず。今は YAML のようなリーダブルな記法もあるし。

参考

Windows 10 の XFinder 使いはそろそろ Tablacus Explorer に移行しても良さそう

長らく XFinder を使ってて、今の Windows 10 でも使ってるけど、そろそろ動作が色々怪しくなってきた。公式のサポートももうじき途絶えるみたいだし。

後継の Tablacus Explorer は知っていたが、昔触った時は「まだまだだな」という印象。以来、特にウォッチしてなかったのだが……先日思いつきで試してみたら、なんと十分使えそうなクオリティに仕上がっていた。乗り換えを決意した。

取り急ぎ、備忘録をまとめておく。

XFinder でやっていたこと

これをそのまま Tablacus Explorer でも実現できることがマストである。

  • 上下二分割
  • タブのロック
  • タブの視覚的強調
    • タブの名前を変える
    • タブの背景色を変える
  • F1 でフォルダ新規、F3 でファイル新規

ほぼ タブを視覚的に見やすく整える 系である。

XFinder でやっていたことは Tablacus Explorer で出来るか

Ans: できる。

Tablacus Explorer はアドオンゲーなので、「この機能無くない?」と思ったらとりあえずアドオンを探す・オプションを見る などすれば良い。

たとえばキーマスタマイズは

  • ツール > アドオン
  • アドオン「キー」を探す
  • オプションを開く

タブの背景色と名前変更については、アドオン追加から以下を追加。

  • ツール > アドオン
  • アドオンを入手
  • 「タブ」などで検索して、以下をインストール
    • タブに色をつける
    • タブに名前をつける

上下二分割については、やはりアドオンで、以下をインストール

  • 分割

キーカスタマイズ設定画面について

ちょっと癖が強いが、慣れたら大丈夫。コマンド記述ではなく 選択肢から選ぶ ようになっている。

たとえば「フォルダ新規」アクションは

  • ツール > アドオン
  • アドオン「キー」のオプション
  • 登録画面が出るので、
    • タイプ:ツール
    • 参照:新規フォルダ
  • 終わったら追加ボタン

これで行ける。

ちなみに既存設定の編集については、設定を選び、いじった後、最後に置換ボタンを押す。

  • 追加ボタン → 表示内容で設定を新しくつくる
  • 置換ボタン → 選択中の設定を、表示内容で更新する

こんな感じ。

練習

画面分割について

アドオンの「分割」を有効にした後、メニューバー右のアイコンから切り替える。

ツールバーを非表示にする

Ans: できない

ただしアドオン > ツールバー から「無効にする」を選べば、アイコンを減らせる。

(練習問題) Tab キーで分割ウィンドウのフォーカスを切り替える

アドオン導入とキーカスタマイズの練習をしてみましょう。

練習問題: 「Tab キーで分割ウィンドウのフォーカスを切り替える(たとえば上下分割で上領域を選択している状態で Tab を押すと、下領域を選択するようにする)」

↑ これを実現してみよう。

答えは最後に書いとく。

XFinder on Windows 10 で発生していた不具合

XFinder on Windows 10 では以下問題が発生していたが、Tablacus Explorer では一通りなくなっている。快適だ。

  • たまに強制終了で落ちる
  • Alt + Cursor で切り替えるとメニューバーが選択状態になってしまう
  • 右クリック二回しないとコンテキストメニューが出ないことがある
  • コンテキストメニューに Lhaplus のエクスプローラー拡張が表示されない

アドオンの自作について

結論を言うと ドキュメントがほぼ無いので無理ゲーだと思う

いやオープンソースだしコードリーディングガチれば(わかる人なら)行けないことも無いだろうが。

以下情報源。

おわりに

XFinder で出来てたことはできるみたいだし、設定画面わかりやすくなってるし、動作も安定している。完全に XFinder の上位互換だと思う。もっと早くから試しておくんだった。

(練習問題の答え)

  • アドオン「分割」と「次のペインに切り替える」をインストールする
  • アドオン「キー」から Tab キーの設定を追加する
    • タイプ:アドオン
    • 参照:次のペインに切り替える

Windows 10 で「オーディオ入力デバイスが見つかりませんでした」ダイアログが出るのを抑止する

何のショートカットキーかはわからないが、たまに「オーディオ入力デバイスが見つかりませんでした」だの「ウィザードを起動できませんでした」だのとダイアログが表示されてイラっとしていた。

ようやく解決方法見つけた。

解決方法

Win + Ctrl + S キー を無効化する。

AutoHotkey を使うなら以下のように。

#^s::Return

これで快適に。

調査過程

表示されるダイアログ

以下二つ。

[Window Title]
ウィザードを起動できませんでした

[Main Instruction]
オーディオ入力デバイスが見つかりませんでした

[Content]
使用しているオーディオ ハードウェアが正しく機能していることを確認してください。[サウンド] コントロール パネルで、オーディオの構成を確認してください。
[Window Title]
ウィザードを起動できませんでした

[Main Instruction]
ウィザードを起動できませんでした

[Content]
使用しているオーディオ ハードウェアが正しく機能していることを確認してください。[サウンド] コントロール パネルで、オーディオの構成を確認してください。

バックで動いてるプロセス

SpeechUXWiz.exe

ググって調べる

英語含めて色んなキーワードでググるが、一向にヒントが見つからない……。

ある日、見つけたのがこのページ。

このページには

多くのものはアルファベット文字との組み合わせで、A~Zまでの全てが埋まっている …… [Ctrl]+[S] Windows音声認識

と書いてある。ショートカットキー入れすぎでしょ……ともあれ、無事 Win + Ctrl + S という答えを見つけたので AutoHotkey で無効化した。

ちなみにこのページにたどり着いたキーワードは「音声認識 windows10 ショートカット」。

AWS CloudFormation でスタック削除時に DELETE IN PROGRESS でブロッキングする件

AWS CloudFormation でスタックを削除しようとすると、DELETE IN PROGRESS 状態が 10 分続き、先に進まないという現象が起きた。普段なら 1 分くらいで終わるのに。

前提

「事前に別のテンプレ base_environment.yaml でつくっておいた環境に、インスタンスを一つ追加する」テンプレ injection.yaml を実行する。

injection.yaml は、以下のように 指定したサブネットに対して EC2 インスタンスをつくる 感じ。

injection.yaml:

Parameters:
  KeyPairName:
    Description: keypair name
    Type: AWS::EC2::KeyPair::KeyName
  AmiId:
    Description: ami id (RHEL-8.0.0_HVM-20190618-x86_64-1-Hourly2-GP2)
    Default: ami-09f31cc5d5eecca1a
    Type: String
  TargetSubnetId:
    Description: subnet id
    Default: subnet-xxxxxxxxxxxxxxxxx
    Type: String

Resources:
  Instance1:
    Type: AWS::EC2::Instance
    Properties: 
      KeyName: !Ref KeyPairName
      ImageId: !Ref AmiId
      AvailabilityZone: "ap-northeast-1a"
      InstanceType: "t3.medium"
      SourceDestCheck: false
      NetworkInterfaces:
      - NetworkInterfaceId: !Ref NetworkInterface1
        DeviceIndex: 0
      Tags:
      - Key: Name
        Value: test-stakiran-instance

  NetworkInterface1:
    Type: AWS::EC2::NetworkInterface
    Properties: 
      PrivateIpAddress: 10.0.10.1
      SubnetId: !Ref TargetSubnetId # ★ここが肝。
      Tags:
      - Key: Name
        Value: test-stakiran-networkinterface

やったこと

  • 1: base_environment.yaml でスタック作成する
  • 2: injection.yaml でスタック作成する
    • 1 でつくったサブネットの id を使う
  • 3: injection.yaml で作成したスタックを削除する

ここでブロッキングが発生する。普段 1~2 分で終わる削除が、10分経っても DELETE COMPLETE にならない。

リソースタブを見ると、

Subnet1 subnet-XXXXXXXXXXXXXXXXX AWS::EC2::Subnet DELETE_IN_PROGRESS

こんな感じで injection.yaml が依存しているサブネット の削除が in progress のままになっている。

対処方法

Ans: base_environment.yaml のスタックも削除する。

AWS の仕様なんだろうが、削除時の挙動はたぶんこんな感じになってる。

  • 削除対象のリソース XXX が他(のスタックでつくったリソース)から利用されている場合、XXX は消さない
  • 内部的にはインターバルで削除試行を試す
    • でも試行の結果はいちいち管理コンソール上には出さない

つまり 「他のスタックでつくったリソース」を消すまで delete in progress のままになってしまう。

この件に関する資料や根拠はある?

Ans: 軽く調べたけど見当たらない。

まず AWS CloudFormation のトラブルシューティング - AWS CloudFormation この辺には書いてなさそう。

唯一、AWS Developer Forums: Attempting to delete stack - stuck at ... にて「50分後に内部エラーで失敗するよ」というコメントはあったが、信ぴょう性は不明。

After 50 minutes it returned delete failed due to "Internal Failure". Attempted delete again, still hanging the same status of delete in progress - user initiated.

おわりに

まあ base_environment.yaml から消すってのは普通はしないだろうけど、今回興味本位でやってみたらこうなったので記事にしとく。

個人的には以下が欲しいなぁ。

  • いつタイムアウトするか(or しないならしないでも良いが)に関する仕様を記した AWS 公式ドキュメント
  • タイムアウト値を変える or 指定する手段(テンプレート中から指定できたら便利そうだが)

後者は待機条件?っての使ったらできそうな気がするけども。

Windows 10 で Python ファイル実行時にコマンドライン引数が渡されない件

拡張子 .py に Python.exe を関連付け、かつ PATH と PATHEXT を通した状態で foobar.py に対して、

$ foobar -h

を実行してもヘルプが出ない。-h の部分が無視されて実行されてしまう。

この問題に対処したのでメモ。

前提

  • Windows 10 Pro
  • Python 3.7.4

対処方法

レジストリをいじる。

  • HKEY_CLASSES_ROOT\Applications\python.exe\shell\open\command キー
  • 既定エントリ

値を以下のように "%1" から %1 %* に変える。

"D:\bin1\python374\python.exe" "%1"

  ↓

"D:\bin1\python374\python.exe" %1 %*

ちなみに HKEY_CLASSES_ROOT\py_auto_file\shell\open\command をいじってもダメだった(assoc コマンドでは .py=py_auto_file なのだが)。

参考: Windows is not passing command line arguments to Python programs executed from the shell - Stack Overflow

Q: なんでこんな対処が必要?

Ans: 関連付けを解決する時に使われる assoc と ftype 設定の仕様だから

以下詳しく見ていく。

たとえば .py に D:\bin1\python374\python.exe を関連付けると、

$ D:\bin1\python374\python.exe foobar.py
→普通はこう書かなきゃいけないところが

$ foobar.py
→これで済むようになる

このようになる。この時、内部的には assoc と ftype により、以下のような設定になっている。

assoc .py=py_auto_file
ftype py_auto_file=D:\bin1\python374\python.exe %1 %*

ここで ftype については、ftype /? でヘルプを読んでみると、こう書いてある。

オープンコマンド内の %0 または %1 は、関連付けを使って開かれるファイル名で置き換えられます。……%* はすべてのパラメーターを取得し、

つまり、内部的には以下のようにして関連付けの解決が行われている。

foobar.py -h

  ↓ .py=py_auto_file だから ftype py_auto_file の設定に従おう

D:\bin1\python374\python.exe %1 %*

  ↓ %1 は「関連付けを使って開かれるファイル名」
  ↓ %* は「すべてのパラメーター」だから、

D:\bin1\python374\python.exe foobar.py -h

ここで、仮に ftype が D:\bin1\python374\python.exe %1 だとしよう( %* が足りない)。どうなるか。

foobar.py -h

  ↓ .py=py_auto_file だから ftype py_auto_file の設定に従おう

D:\bin1\python374\python.exe %1

  ↓ %1 は「関連付けを使って開かれるファイル名」

D:\bin1\python374\python.exe foobar.py

このようになってしまい、-h のコマンドライン引数部分が常にカットされてしまう結果となる。

参考:

Q: なんで Applications\python.exe だと直るけど py_auto_file だと直らないの?

Ans: 優先順位の問題で Applications\Python.exe の設定が優先される から(たぶん)。

Application Registration - Windows applications - Microsoft Docs を見ていると、どうもアプリの関連付け設定箇所は複数あり、かつ優先順位(priority) があるように読める。

記述は見当たらなかったが、HKEY_CLASSES_ROOT\XXXX よりも HKEY_CLASSES_ROOT\Applications\XXXX.exe の方が優先順位が高いのだと思われる。

つまり、HKEY_CLASSES_ROOT\Applications\Python.exe 側が %1 となっていたら、いくら HKEY_CLASSES_ROOT\py_auto_file 側を %1 %* にしても、使われるのは優先順位の高い Applications\Python.exe 側の %1 になる、という話。

Slack ワークフローを使うと何ができるのか、要約と事例を集めてみた

先日 Slack にワークフローという自動化機能がリリースされた。どんな機能なのだろう?

色々と調査と試行を行ったので、要約と事例をまとめてみる。

要約

ワークフローとは?

Slack 上で頻出する「特定の人に特定のメッセージを投げたい」を省力化するための機能。

  • ワークフロー = 「指定した出来事」が起きたら「指定したメッセージ」を「指定チャンネル or 個人」に投げる、を自動化したもの
  • ワークフロービルダーという設定画面からつくる
    • プログラミングは不要
    • 画面ポチポチでつくれる感じ

ワークフローで何ができるの?

ざっくり言えば、以下二点。

  • ピン留めで周知する必要がなくなる
    • チャンネル入室時に案内メッセージが送信されるようにできる
    • フォームを設置できる(回答してほしい内容を制限&統一化できる)
  • 絵文字リアクションがついた時に通知が届くようにできる

使い勝手はどう?

機能不足感はあるが、簡単に使えるのが良い。

もう少し詳しく

→ こっち見て: Slack のワークフロー機能を少し試したのでまとめた - stamemo

事例

ググって見つかったもの、Twitter でツイートされていたもの、Qiita に投稿されていたものなどを雑多に紹介。ただし遊びやネタ的な使い方は割愛。

参考:

オンボーディング

オンボーディングとはざっくり言えば「新規参入者に対して必要事項を素早く漏れなく教える」こと。詳しくは IT用語辞典 e-Words あたりを。まあ「新人に対する効率的なガイド」といったニュアンスか。

さて、定義はともかく、ワークフローを使えば「指定チャンネル入室時に指定メッセージを送信」ができるので、新人向けの案内も出せる。

いちいち「ピン留めしたこれ見てね」とか「メンバー増えてきたので再周知しますね → ピン留めしたメッセージを再投稿」とかいった手間もない。

日報や週報

日報や週報といった定期的に報告させたいネタは、人によって内容にばらつきが生じやすい。管理者やリーダーは「読みづらい」「結構流し読みしてる」ことも多いだろう。

ワークフローを使えば「指定チャンネルに "日報用フォーム"」を設置できるので、フォーマットも統一できるし、送信先をチャンネルではなく管理者自身にすれば「私だけが見えるよ(チームメンバーには見えないから本音書いていいよ」状態もできたりする。

まあ透明性のためにも、送信先はチャンネルにするのが良いとは思うが。

申請事項や依頼事項

請求書の依頼、物品や書籍の購入依頼、経費精算など雑務系の依頼は多数存在する。

ワークフローを使えば、指定チャンネルに指定フォームを設置することで一元化を図れる。

問い合わせ対応

人事への問い合わせをSlackワークフローで仕組み化してみた|Feedforceのnote の事例が興味深い。

フォームにてカテゴリ、質問内容、回答先を選ばせている。

  • フォーム
    • 質問1:「選択制」でカテゴリを選ばせる
    • 質問2:「長い回答」で質問内容を書かせる
    • 回答先:「選択制」で人事がどこに回答するかを選ばせる(パブリック or 個人宛)
  • 運用
    • フォームから送信された後、誰が対応するかは手動で決める
    • 『労務メンバーはこれを見て、誰が対応するかを決めます』

優れた Web サービスの「お問い合わせフォーム」みたいなものを、手軽に Slack 上で実現できるわけだ。

絵文字がついたメッセージをログる

これは非常に賢いなと思った事例だが、

2: 以後コンテンツ(ヘルプページ)化できそうなら 「コンテンツ化!」スタンプ貼る

Slack には「指定した絵文字でリアクションされたら」「指定チャンネル or 人に」「指定メッセージを送る」というワークフローがつくれる。また変数として「リアクションがついたメッセージ」も使える。

結果として「指定した絵文字がついたら、そのメッセージを別チャンネルに送信する(複製する)」ことができる。

つまり絵文字がついたことを契機として、特定のメッセージを別のチャンネルに保存できるのだ。

早く返事が欲しい場合の「~~さんが反応しました」通知

絵文字リアクションは通知されないため、「この対応終わったらここにこの絵文字つけてくれ」的なことをしても、いつ誰がつけたのかがわからない。メッセージ主はいちいち何度もチェックしなきゃいけない。

しかしワークフローを使えば「指定絵文字がついた瞬間、その旨をメッセージとして出す」ことができる。メッセージであれば通知もされる。結果として、「誰かが絵文字をつけたらすぐにわかる」を実現できる。

※もっとも Slack の良さは非同期コミュニケーションにあるため、このような「反応を急かす」運用は多用するべきではないのが。

ノウハウ共有系チャンネルの投稿フォーム

チャンネルとして「ノウハウを投稿して貯める」系のものを運用しているケースがある。この手のチャンネルでは「投稿者によってフォーマットがバラバラで見づらい」という問題が起こりがちだ。

ワークフローならフォームを設置することで解決できる。

ただし、フォームが煩雑すぎると投稿ハードルが上がるのには注意が必要だ。適宜、必須回答をオフにして「別に入力しなくてもいいっすよ」という軽さを出そう。逆に、ある程度の品質を担保したいのなら、バリバリ必須回答にする。

おわりに

Slack のワークフロー、楽しい。

今後の機能拡張と日本語のエラー強化に期待する。

Slack のワークフロービルダーでアクションメニュー作成時になぜか「ワークフローの保存中に問題が発生しました」が出る

結論を言うと ワークフロー名がたぶんおかしい ので直すこと。

  • 例1: 全角記号(括弧とか)が含まれている
  • 例2: 名前が長すぎる

発生する問題

ワークフロービルダーでアクションメニューを作成する際、なぜか「ワークフローの保存中に問題が発生しました。」と出て作成に失敗する。

console.log を見てみると、

... missions.apps.create is REJECTED: API not ok invalid_name_specials

だとか

... missions.apps.create is REJECTED: API not ok invalid_name_maxlength

などと出ている。

しかしアクションメニュー作成画面の「短い名前」欄には、許可されてない文字(一般的には半角記号類)は入れてないし、文字数も上限には全然足りてる。なのに起きる。

原因

おそらくだが、(アクションメニューの設定を指定する前段階で指定する) ワークフロー名が不正な名前になってしまっている のが原因と思われる。

通常ならワークフロー名の入力時にバリデーションされる(半角記号があったら次に進めない)し、文字数超過できないようガードもかかっている。しかし 日本語になるとバリデーションもガードも緩むようだ

結果として、最終的にアクションメニューを作成するタイミングでしくじる。

  • アクションメニュー作成時に入力するパラメーターは三つ
    • ワークフロー名 ★ここでしくじる
    • アクションメニュー設置先チャンネル名
    • アクションメニュー名(短い名前)

FAQ

原因を詳しく調べようとしたけど、結局何もわからず。その辺を FAQ 形式でまとめとく。

Q: 許可されてない文字とは具体的に何か?

わかりません。

まだドキュメントは整備されてない模様。

※ちなみに私が試したのは全角丸括弧 () のみ。他にどんな全角記号が使えないかはわかってない。ただ、全角丸括弧が使えないことから「全角記号全般も使えないのでは?」と推測して書いてるだけ。

Q: ワークフロー名が日本語で 80 文字以内なのに invalid_name_maxlength が出るがなぜ?

わかりません。

バグじゃないかな。

Q: API ドキュメント見たらヒントあるんじゃないの?

なさそうです。

API Methods - Slack 見てみましたけど、workflow 的なメソッドは見当たりません。まだ未対応なのか、対応はしてるけどドキュメントはまだなのか。

Slack のワークフロー機能を少し試したのでまとめた

Slack にワークフローという新機能が追加された。なんか自動化できるらしい?面白そうじゃないか、というわけで簡単に触ってみたのでまとめる。

ワークフロー機能とは?

指定したイベントが起きた時に、指定したアクションを実行させる新機能。

ワークフローをつくるには?

左上メニュー > ワークフロービルダー

イベントとして指定できるのは?

3 種類ある。

  • 誰かが指定チャンネルに参加した
  • 誰かが指定チャンネル内の「アクションメニュー」から指定項目を選んだ
  • 誰かが指定絵文字をリアクションで付けた

アクションとして指定できるのは?

2 種類ある。

  • 指定メンバーやチャンネルに指定メッセージを送る(変数あり)
  • 指定フォームをつくって入力させ、入力内容を指定メンバーやチャンネルに送る

ハマりどころ

チャンネル指定時はキーワード検索で絞る

デフォでは全チャンネルが表示されないが、明示的にキーワードを打てば(ヒットしたものが)表示させる。

たとえば #workflow-test というチャンネルをつくっていても、デフォでは選択肢に出てこない(ことがある)が、wo とか打てば表示される。

エラーの原因究明はしんどいかも

まだ作り込みが不十分なのか、エラーメッセージが 「問題が発生しました」しか言ってくれない(原因がわからない) ので原因究明がしんどいかもしんない。Slack さん、原因も出してくれるよう頼んます。

以下いくつか例を。

ワークフローのインポート中に問題が発生しました。

エクスポートした json を少し変えてインポートしてみたら起きた。id 被ってて重複扱いとか?

ワークフローの保存中に問題が発生しました。

#random にワークフローを追加しようとしたら起きた。原因はよくわからん。

こっそり仕込むことはできない

ワークフローを設置した先にチャンネルには「~~さんが~~をつくりました」など更新通知が飛ぶので、 「個人的な便宜のためにこっそりつくるか……」なんてことはできない

インポート、エクスポートもできる

エクスポートすると (ワークフロー名).json をダウンロードできる。中身は以下のような感じ。

{
  "source_id": "271548516294212359",
  "version": "1",
  "workflow": {
    "name": "(ワークフローの名前)",
    "blueprint": {
      "version": "1",
      "trigger": {
        "type": "reaction_added",
        "id": "...",
        "config": {
          "channel": {
            ...
          },
          "reactions": [
            {
              ...
            }
          ]
        }
      },
      "steps": [
        {
          "type": "message",
          "id": "...",
          "config": {
            ...
          }
        },
        ...
      ]
    }
  }
}

インポートはまだ試してない(上述したが微修正した json をインポートしても動かんかった)。追々試そうかな。

ワークフローの用途は?

パッと思いつかないけど、たとえば以下。

  • 絵文字がついた時に「~~さんが付けたよ」と通知する
  • アンケート
    • 募りたい時にアクションメニュー用意して「ここから入力してね」と告知するとか
  • 強制自己紹介
    • チャンネル入った時に自己紹介フォーム表示させて入れてもらう

他にもアイデア次第で色々できそう。まだ出たばかりで記事も少ないが、そのうち記事も増えてくるだろうから、改めて調べてみるとしよう。

AWS CloudFormation テンプレート中で使う AMI ID のメンテナンス方法

AMI ID をハードコードしていると、そのうち AMI が見つからなくなり以下のような CREATE FAILED になる。

API: ec2:RunInstances Not authorized for images: [ami-XXXXXXXXXXXXXXXXX]

これに対処するにはどうすればいいのだろう?

まとめ

  • FAILED が起きた時に素早く対処できるようにする
    • AMI ID をパラメータ化する(ハードコード時よりもいじりやすい)
    • 管理コンソールで AMI ID で検索して有効無効を調べる
    • awscli で「有効な AMI ID」を事前にゲットしておく
  • FAILED が起きないよう CloudFormation 側で自動で有効な AMI ID を指定させる
    • 「有効な AMI ID をゲットする処理」をする Lambda + s3 にアップ + CloudFormation 側でそれ取ってきて実行

方法1: FAILED になった時に素早く対処できるようにする

これは FAILED を防ぐのではなく「FAILED が起きた時に簡単に別の AMI ID を指定できるようにする」というアプローチ。

詳しいやり方は色々ある(組み合わせる)。以下雑多に取り上げる。

AMI ID の指定をパラメータ化する

FAILED 時、ハードコードだと「Resources.InstanceServerA.Properties.ImageId を変えてくれ」となるが、これはコードに馴染みがない人にはハードルが高い。

一方、このパラメータ化なら「AMIServerA のパラメータに、有効な AMI ID を指定してくれ」と言えば済む。画面操作なので(AWS CloudFormation の管理画面を使っている程度のリテラシーでも)ハードルは低い。

Parameters:
  AMIServerA:
    Description: ServerA AMI ID.
    Default: ami-XXXXXXXXXXXXXXXXX
    Type: String

Resources:
  InstanceServerA:
    Type: AWS::EC2::Instance
    Properties: 
      ImageId: !Ref AMIServerA

AMI ID が有効かどうかを調べる

  • 1: 管理コンソール > EC2 > インスタンスの作成
  • 2: AMI 選択画面で、AMI ID で検索

有効な場合、コミュニティ AMI に 1 件だけヒットする。

これが 0 件の場合、当該 AMI ID は存在しない(のでスタック流した時に Not authorized for images で FAILED になる)。

AWS CLI で「有効な AMI ID」を事前に取得しておく

いちいち管理コンソールから探す手間を省ける。

参考:

やり方は二つあって、まず古いやり方では aws ec2 describe-images を使って、AMI 名のワイルドカードでフィルタする模様。ソートして一番上を取り出す、など面倒くさかった。

新たなやり方では aws ssm get-parameters (URI) を使って、指定 AMI の最新バージョン(の AMI ID)を 常に同じ URI で 取れる模様。

方法2: そもそも FAILED が起きないようにする(自動で有効な AMI ID を使う)

方法 1 は手動であり、FAILED を起こさないようにすることができないが、これを可能にするのが方法2。

とりあえず一つだけ見つけた。Lambda と連携させれば良いみたい。

参考: Walkthrough: Looking Up Amazon Machine Image IDs - AWS CloudFormation

実装は何百行となっているが、要点はこんな感じっぽい。

  • 1: 「有効な AMI ID を取得する Lambda パッケージ」を S3 にアップしておく
    • この Lambda は「Windows_Server-2008-SP2-English-32Bit-Base-*」みたいにワイルドカードで AMI を探す
  • 2: テンプレートでは AWS::Lambda::Function などを駆使して、1: の Lambda パッケージを取得&実行&結果を得る

AWS CLI を使って CloudFormation スタック作成をコマンドラインで実行する

管理コンソールからいちいちポチポチするのがだるいので調べてみた。

サマリー

必要なのは以下二つ。

  • 必要なアクセスキーは事前につくって入手しておく
  • aws cloudformation create-stack コマンドを使う

コマンドライン

$ aws cloudformation create-stack --stack-name testFromCreateStack --template-body myEnv.yaml --capabilities CAPABILITY_IAM --parameters ParameterKey=NameTagValue,ParameterValue=stakiran ParameterKey=KeyPairName,ParameterValue=keypair_stakiran_gen

引数が長ったらしいが、以下のとおり

  • スタック名
  • アップするテンプレートファイル
  • (テンプレート中で IAM つくってる場合は)その旨に同意するための指定
  • 各パラメータの指定

アクセスキー

IAM からユーザーつくって、アクセスキーとかメモして、このユーザーに以下のポリシーを付ける。

問題はポリシーをどうするかだけど、結論としては以下の権限が必要。

  • a) CloudFormation でスタックをつくる、消す系の権限
  • b) テンプレートから操作するリソースに関するすべての権限

b) が曲者で、いちいち洗い出して列挙するのが面倒くさすぎる。また、列挙したとしてもすぐエラーになって「実は iam:PutRolePolicy が必要やねん」「iam:AddRoleToInstanceProfile が足りとらんぞおい」と 「暗黙のうちに依存している分」が指定されてない 問題に苦しむ。

……で、面倒くさくなったので、ワイルドカードでフルコンにした。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "cloudformation:CreateStack",
                "cloudformation:ListStacks",
                "cloudformation:UpdateStack",
                "cloudformation:DeleteStack",
                "cloudformation:TagResource",
                "cloudformation:ValidateTemplate",
                "iam:*",
                "ec2:*",
                "route53:*"
            ],
            "Resource": "*"
        }
    ]
}

無論、ずっと使うのは危ないので、終わったらアクセスキーは消しとく。今回は実験したかっただけなので一度成功を確認できたところで消しといた。

動作確認方法

create-stack

「リクエスト送信の可否」が非同期で返ってくる。失敗時はエラーメッセージ。

スタック作成の成否自体はわからない ので、次の方法を。

create-stack の後

一番簡単なのは管理コンソールにログインして、CREATE FAILED で落ちてないか見る。

もう少し頑張ってここもコマンドライン完結したいなら、describe-stack を 定期的に実行して CREATE_COMPLETE になるまで監視する など工夫する必要があるだろう?(まだ試してない)

以下は describe-stack の実行例。

$ aws cloudformation describe-stacks

出力。

{
    "Stacks": [
        {
            "StackId": "arn:aws:cloudformation:ap-northeast-1:...",
            "StackName": "...",
            "Description": "...",
            "Parameters": [
                {
                    "ParameterKey": "KeyPair",
                    "ParameterValue": "hogefugapiyo"
                },
                ...
            ],
            ...
            "StackStatus": "CREATE_COMPLETE", // ★ここを監視する感じか
            ...
        },
        {
            "StackId": ...,
            ...
        },
        ...
    ]
}

所感

  • やろうと思えばコマンドライン完結もできそう
  • アクセスキー運用の良いプラクティスって無いんだろうか?
    • フルコンポリシー + アクセスキー注意深く管理して、以外に何かある?

参考

バッチファイルから start した時にウィンドウが背面に隠れてしまう問題に対処する

バッチファイルから start でアプリ(今回は mspaint)を起動すると、なぜかウィンドウが背面に隠れてしまう(前面に表示されてくれない)

単純なバッチファイルではちゃんと前面に出るのに、 new.bat みたいな煩雑なバッチファイルになるとなぜか出てこなくなる

なぜだろう?

対処方法はどうすればいいのだろう?(ちなみにバッチファイルだけで完結したいので win32api 使うとかはナシで)

※new.bat とは拙作 canvasp の同梱バッチファイル。画像ファイルを簡単に用意してくれるツールです。よかったら使ってみてね。

原因は何?

わからないです。

下記記事によると「親ウィンドウを認識していないから」とのことだが、いまいちピンと来ない。今回の new.bat は煩雑だが set と for /F "usebackq" を使っているだけであり、親ウィンドウどうこう的な処理は何もしてないと思っているのだが。

対処方法は?

start で開く部分の処理を別のバッチファイル opener.bat に移し、opener.bat を start する

Before: 背面に隠れていた時のソース

start "" "%PAINT_APP_PATH%" "%DATA_DIRNAME%\%filename%"

環境変数もりもりだが、要するに

start "" (mspaintのパス) (画像ファイル)

という書き方になっている。これが実行されると、なぜかペイントのウィンドウが背面に表示される。

After: 前面に表示されるソース

まず呼び出し元はこう。

call open_image.bat "%DATA_DIRNAME%\%filename%"

open_image.bat という 指定されたファイルをペイントで開くバッチファイル を start している。

で、open_image.bat は以下のとおり。

@echo off
setlocal
set PAINT_APP_PATH=mspaint.exe
start "" "%PAINT_APP_PATH%" %*

一般化すると……

Before:

start "" (mspaintのパス) (画像ファイル)

After:

rem 呼び出し元
start "" (指定ファイルをペイントで開くバッチファイル) (画像ファイル)
rem 指定ファイルをペイントで開くバッチファイル
start "" (mspaintのパス) %*

実際のソース

細かい解説はしないが、リンクだけ置いておく。

Before:

After:

なぜこれで前面に表示されるようになるか

ぶっちゃけわからん

ただ、以下はわかっていたので、

  • a) 単に start を書いただけのバッチファイル → 前面に出る
  • b) new.bat などなんか煩雑なバッチファイル → 前面に出ない(背面に隠れちゃう)

だったら start 使う部分だけ「start するだけのバッチファイル」として外に出せば、a) になるんじゃないか と考えて試してみたらビンゴだった、という話。

Windows Defender(リアルタイム保護)が勝手にオンになるのを防ぐ

他のセキュリティソフトを入れている場合、Windows Defender は要らない。しかしデフォでは無効にする手段がない(オフにしてもしばらくしたら勝手にオンになってしまう)。

煩わしいので勝手にオンにならないようにする。

手順

「自動でオンにするやつ」を殺すバッチファイルをつくり、これを「指定間隔で実行する仕組み」に登録する。

手順1. defender_off.bat をつくる

以下のようなバッチファイルをつくる。

schtasks /delete /tn "\Microsoft\Windows\Windows Defender\Windows Defender Scheduled Scan" /f
schtasks /delete /tn "\Microsoft\Windows\Windows Defender\Windows Defender Cache Maintenance" /f
schtasks /delete /tn "\Microsoft\Windows\Windows Defender\Windows Defender Cleanup" /f
schtasks /delete /tn "\Microsoft\Windows\Windows Defender\Windows Defender Verification" /f
exit /b

手順2. タスクスケジューラに登録する

  • control schedtasks を実行(タスクスケジューラを開く)
  • タスクスケジューラ(ローカル) > タスクスケジューラライブラリ と辿る
  • 右ペイン > 右クリックから新しいタスクの作成
    • トリガーは「毎日 xx:yy」に起動にする
    • 操作は「プログラムの開始」として defender_off.bat のフルパスを指定する

xx:yy を何時何分にするかを知るには、Microsoft\Windows\Windows Defender のタスクたちの「前回の実行時刻」列を見る。たとえば 15:30 であれば、15:30 にそのタスクが実行されて「勝手にオンにする」が発動した(と思われる)ので、xx:yy は 15:29 とか 15:20 とかちょっと前にすれば良い。

解説

リアルタイム保護が勝手にオンになるのは、上記のスケジュールタスクが働いているせい。そして上記スケジュールは一度消しても勝手に復活させられる(犯人は不明だが Windows Update 系のタスクとか?)。

つまり以下のようなロジックが働いているので、

  • a) Microsoft\Windows\Windows Defender のタスクが復活する
  • b) タスクたちのトリガー(発動条件)が満たされると、勝手にオンにする処理が発動する

b) に移る前に a) のタスクを消去できればいい。

この消去を行うバッチファイルが手順1. の defender_off.bat で、このバッチファイルを b) の前に呼び出すのが手順2。

指定タイトルを持つコマンドプロンプトウィンドウ(cmd.exe ウィンドウ)を Kill する

たとえば「15分後にリマインド」というタイトルを持つ cmd.exe を殺したい場合。

結論

以下のようになる。

for /f "tokens=2" %A in ('tasklist /v ^| findstr /i "15分後にリマインド"') do taskkill /PID %A /f /t

別のタイトルで利用する場合は findstr /i の値を変える。

殺しやすいように cmd.exe ウィンドウ(を表示するバッチファイル)のタイトルをあらかじめ title 命令で変えておくのもアリ。

解説

アプローチ

まず cmd.exe ウィンドウを殺すアプローチは以下となる。

  • 1: 「殺したい cmd.exe の PID」を入手する
  • 2: PID があれば taskkill コマンドで殺せるので、1: の PID を指定して taskkill する

PID は tasklist /v コマンドで知ることができる。

ただし tasklist は動いてるプロセス全部の情報を出すので、殺したい cmd.exe ウィンドウのみの情報が欲しい。これを findstr /i で抽出する。

抽出すると、以下のような情報になっている。PID が欲しい。

$ tasklist /v | findstr /i "秀丸"
Hidemaru.exe                  1234 Console                    1      9,999 K Running         USERNAME                                       0:12:34 blog.md (更新) - 秀丸

PID は 1234 の部分。

……このあたりを、上手くコマンドを組み合わせて実現すれば良い。

コマンドラインを組み立てる

まずは PID を含む部分を抽出する。

tasklist /v | findstr /i "15分後にリマインド"

この結果から PID 部分だけ取りたい。Linux なら awk コマンドがあるが、Windows にはない。どうするか。for /f token を使う。

for /f "tokens=2" %A in ('tasklist /v ^| findstr /i "15分後にリマインド"') do ……

これで「括弧内の実行結果の 2 番目の要素を %A として取り出す」的な意味になる。ただし括弧内は一部記号のエスケープが必要(パイプ | 前のハット ^)。……書き方ややこしい。

ともあれ、これで %A に PID が入るので、あとはこれを使って taskkill するコマンドを書く。

for /f "tokens=2" %A in ('tasklist /v ^| findstr /i "15分後にリマインド"') do taskkill /PID %A /f /t

ただし taskkill のオプションとして /f 強制終了と、/t 子プロセスも殺す、の二つが必要。この二つがないと cmd.exe は死なない。

参考

5年ぶりくらいに Firefox を Win7 から Win10 に移行したのでメモ

まずは 公式のプロファイル移行手順 に従ってデータを丸々移して、Firefox を新たなプロファイルで立ち上げる。この後の話。

ダウンロード先の修正

以下のように修正。

C:\root\Download

D:\root\Download

自動プロキシースクリプトの修正

以下のように修正。

file:///C:/root/data/proxy.pac

file:///D:/root/data/proxy.pac

ただし現在、会社では https://(イントラネット)/proxy.pac のようになっていて、これを指定することが推奨されていたが、いちいちイントラネットを通信させるのは遅いので、この proxy.pac をローカル D:/root/data に置いてから指定した。

ローカルに置いたファイル(file プロトコル)を読めるようにする

about:config > privacy.file_unique_origin を false にする。

v68 以降から必要になるみたい。

参考: Reason: CORS request not HTTP - HTTP - MDN

(余談) プロファイル移行手順の要約

事前に %appdata% 配下にあるプロファイル設定を事前にバックアップしておくことが前提。

例: AppData\Roaming\Mozilla\Firefox\Profiles\xxxxxxxx.(profilename)

移行手順は以下のとおり。

  • 1: 新しい環境で firefox -p を起動
  • 2: プロファイルマネージャが開くので、適当に新しいプロファイル名 yyy をつくる
  • 3: %appdata% 配下にフォルダができるので、そこに上記でバックアップしたファイル達をまとめて放り込む
  • 4: firefox -p の画面から、新しく作ったプロファイルで firefox を起動

これで行けた。