Test::Specに関するメモ
2024年にもなってperl5の話題。
古いスクリプトをいじっているとTest::Moreだけで書いてあったテストが読みづらくて仕方なかったのでTest::Specで書き直してみた。
以下のような書き方が良い。
describe "ほげほげすると" => sub {
it "ふがふができる" => sub {
ok $result or diag "情報";
};
};
こうするとテスト失敗時に以下のような出力となる。
# Failed test 'ほげほげすると ふがふができる' # at example.t line 10. # 情報
ポイントは`ok`の使い方。
`ok($result,"test name")`と書いてしまうと、test nameが出力されてしまい、describeとitに書いた文が出力されない。
またdiagを書けばテスト失敗時の手がかりを増やせる。
俺はただwindows 10のvscodeからgit pushしたかっただけ
前書き
Visual Code Studioが最近人気ですね。(要出典)
会社のMacで便利に使ってます。
家のWindowsでも使いはじめたのですが、なぜかvscodeのgit pushを実行するとPermission Deniedのアラートが表示されてしまっていました。
Git Bashからならば(毎回sshのパスフレーズは聞かれていましたが)git push出来ていたので放置していたのですが、ちょっと気になってきたので腰をあげて解決することにしました。
状況
Version Control in Visual Studio Code にてWindowsのVisual Studio CodeでGitを使う場合はGit for Windowsをインストールすることが必要とされていたため従いました。
Git for Windowsをインストールしたし、bashに慣れていたため、Integrated Terminal in Visual Studio Code に従いvscodeのターミナルにGit Bashを採用しました。
解決例
まとめ
- 2019/3時点でWindows 10にインストール済みのOpenSSH(ssh.exe)を使う
- ssh-agent.exeを使う(windowsのサービスとして起動する)
- Windows起動時に毎回ssh-add.exeで秘密鍵をssh-agent.exeに登録する
これでvscodeからもGit Bashからもgit pushできるようになりました。
詳細
2019/3時点でWindows 10にインストール済みのOpenSSH(ssh.exe)を使う
vscodeからgit pushするときにOpenSSHを使うため、C:\Users\<username>\.gitconfigに以下を記述。
[core]
sshCommand = C:/Windows/System32/OpenSSH/ssh.exe
Git Bashからgit pushするときに使われるsshをOpenSSHにするため、C:\Users\<username>\.bash_profileに以下を記述。
alias ssh="/c/Windows/System32/OpenSSH/ssh.exe"
おまけで、WindowsのOpenSSHを使うようになったので、C:\Users\<username>\.ssh\configにあるIdentityFileのパス記述形式を修正。
Host bitbucket.org
IdentityFile C:\Users\<username>\id_rsa
User git
ssh-agent.exeを使う(windowsのサービスとして起動する)
こちらの通り。
Windows起動時に毎回ssh-add.exeで秘密鍵をssh-agent.exeに登録する
コマンドプロンプトを起動し以下を実行。
C:\Users\ajishixo>ssh-add C:\Users\<username>\id_rsa
Enter passphrase for C:\Users\<username>\id_rsa:
Identity added: C:\Users\<username>\id_rsa (C:\Users\<username>\id_rsa)
試行錯誤のメモ(箇条書き)
- vscodeからgit pushするとパスワードも聞かれずPermission Deniedが表示されていた。
- sshCommandのsshに-vvvオプションをつけてみると /dev/tty が No such file or directory だった。
-
ssh.exe misbehaves within Powershell · Issue #1041 · PowerShell/Win32-OpenSSH · GitHub によると解決してそうだが・・・。
-
Windows PowerShell の OpenSSH でパスワードを正しく入れてもログインできない。 - 中野智文のブログ に同意で、解決してないと判断。
- さらに、詳しくは分からないが、/dev/tty の問題が解決したところで、vscodeがパスワードを求めるプロンプトなどを表示する仕組みも必要なはず。
- 毎回パスワードを聞かれる状態の解消を優先すべしと判断。
- ssh-agentの有効化に至る。
VSCodeをUbuntu 14.04 (32bit)にインストールする方法
2017/05/14での状況です。(この時点であまり存在しない環境だろうけどメモ。)
成功事例
まずは以下から .deb (32 bit) をダウンロード。
そして以下のコマンドを実行。
$ sudo dpkg -i <file>.deb
終わり。
失敗事例
.tar.gzをダウンロードして展開したものを起動すると以下のエラーが出力されて失敗する。
$ bin/VSCode-linux-ia32/Code [6064:0514/111845:ERROR:browser_main_loop.cc(173)] Running without the SUID sandbox! See https://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment for more information on developing with the sandbox on. bash: 端末プロセスグループを設定できません (-1): デバイスに対する不適切なioctlです bash: このシェルではジョブ制御が無効になっています [6064:0514/111852:ERROR:desktop_window_tree_host_x11.cc(810)] Not implemented reached in virtual void views::DesktopWindowTreeHostX11::InitModalType(ui::ModalType)
調べた限りではLinux SUID Sandboxは使えず、むしろ使わないほうが良いとのこと。
https://chromium.googlesource.com/chromium/src/+/master/docs/linux_suid_sandbox_development.md
Cloud Functions for FirebaseでVue.jsのSSRを試してみる
Firebaseがcloudfunctions.netと連携したことにより、Javascriptを使って動的にHTMLを構築して返すことが出来るようになりました。
さらに流行りのVue.jsによるサーバサイドレンダリングが出来れば最高です。試してみます。
※以下はfirebase上にprojectを作成済みであるとして記述しています。
init&deploy
まずは動的にHTMLを返すまでの手順を確認します。
$ firebase init functions $ tree -L 2 . ├── firebase.json └── functions ├── index.js ├── node_modules └── package.json
functions/index.jsを開いてコメントアウトされている行を有効にします。
var functions = require('firebase-functions');
exports.helloWorld = functions.https.onRequest((request, response) => {
response.send("Hello from Firebase!");
})
そしてfirebase deployコマンドでデプロイします。
$ firebase deploy // 省略 Function URL (helloWorld): https://us-central1-(project).cloudfunctions.net/helloWorld
出力されたURLにWebブラウザでアクセスすると"Hello from Firebase!"と表示されました。
Vue.jsの導入
サーバサイドレンダリングはクライアントサイドレンダリングとの共通化を考えなければシンプルです。
まずは必要なnpmをダウンロードします。
$ cd functions $ npm install vue vue-server-renderer --save
またfunctions/index.jsを開いて編集します。
var Vue = require('vue');
var renderer = require('vue-server-renderer').createRenderer();
var functions = require('firebase-functions');
exports.helloWorld = functions.https.onRequest((request, response) => {
renderer.renderToString(
new Vue({
template: ''
+ '<!DOCTYPE html>'
+ '<html>'
+ '<head>'
+ ' <title>Vue SSR Sample</title>'
+ '</head>'
+ '<body>'
+ ' <p>Server Side Rendered</p>'
+ '</body>'
+ '</html>'
}),
(error, html) => {
if (error) { return response.status(500).send('Server Error') }
response.send( html )
}
)
})
これでfirebase deployすると"Vue SSR Sample"というタイトルのページが返るようになりました。
realtime databaseの読み書き
サーバサイドレンダリングに出来てクライアントサイドレンダリングに出来ないこととして大きなことは、metaタグの出力を動的に変更することです。
realtime databaseにあるデータを出力するようにコードを修正します。
まずはdatabaseにデータを入れます。以下は初期化から行っています。
$ firebase init database
$ echo '{"description": "Vue SSR Sample with Firebase Realtime Database"}' | firebase database:set /helloworld --confirm
$ firebase database:get /
{"helloworld":{"description":"Vue SSR Sample with Firebase Realtime Database"}}
そしてmeta descriptionをdatabaseの内容に書き換えるようコードを修正します。
var Vue = require('vue');
var renderer = require('vue-server-renderer').createRenderer();
var functions = require('firebase-functions');
var admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
var data = {description: ""};
var vm = new Vue({
template: ''
+ '<!DOCTYPE html>'
+ '<html>'
+ '<head>'
+ ' <title>Vue SSR Sample</title>'
+ ' <meta name="description" v-bind:content="description" />'
+ '</head>'
+ '<body>'
+ ' <p>Server Side Rendered</p>'
+ '</body>'
+ '</html>',
data: data
});
exports.helloWorld = functions.https.onRequest((request, response) => {
admin.database().ref("/helloworld/description").once("value")
.then(snapshot => {
data.description = snapshot.val();
renderer.renderToString(
vm,
(error, html) => {
if (error) { return response.status(500).send('Server Error') }
response.send( html )
}
)
})
.catch(error => {
console.log(error);
})
;
})
webブラウザでアクセスしてhtmlソースコードを見てみるとmeta descriptionが期待通りに「Vue SSR Sample with Firebase Realtime Database」になっていました。
今後
クライアントサイドレンダリングとサーバサイドレンダリングの共通化を試してみたいですね。
また別の話ですけど生成されるURLがシンプルではないので改善されることを期待してます。
perl6をインストールした後cat.plをcat.p6に書き換える
リリースされてそろそろ一年。
使ってみないとperl6のことがわからないので使ってみる。
まずは一番単純なcatコマンドのように動くコマンド作りから。
rakudo & panda インストール
rakudobrewというPerlBrewのようなスクリプトでインストール。簡単。
How to get Rakudo Perl 6 | rakudo.org
ドキュメントをインストール
そもそもperl6の書き方がわからない。
webで調べてもいいのですが、perldocを重宝していたので同じものが無いかと調べてみると p6doc というものがあったのでインストール。
$ panda install p6doc
自分の環境では libssl-dev の追加が必要だった。
また、p6docコマンドがPATHの通ったところに置かれなかったので調整した。
さらに、使っていると以下のコマンドの実行を勧められたので実行した。
$ p6doc-index build
cat.plからcat.p6へ
cat.pl
cat.plの挙動は以下を想定している。
$ cat helloworld Hello World $ ./cat.pl helloworld Hello World $ cat helloworld | ./cat.pl Hello World
実装は以下の通り。
#!/usr/bin/env perl
use strict;
use warnings;
while (<>) {
print;
}
cat.p6
先に結果を載せておく。
#!/usr/bin/env perl6
use strict;
for (lines) {
.say;
}
try & error
perl6で実行
cat.plをperl6で実行するよう書き換え。
#!/usr/bin/env perl6
use strict;
use warnings;
while (<>) {
print;
}
実行すると以下のエラーが出る。
$ ./cat.pl helloworld
===SORRY!===
Could not find warnings at line 4 in:
/home/ajishixo/.perl6
/home/ajishixo/.rakudobrew/moar-nom/install/share/perl6/site
/home/ajishixo/.rakudobrew/moar-nom/install/share/perl6/vendor
/home/ajishixo/.rakudobrew/moar-nom/install/share/perl6
CompUnit::Repository::AbsolutePath<189992464>
CompUnit::Repository::NQP<191589208>
CompUnit::Repository::Perl5<191589232>
warningsプラグマは無くなった様子。
use warnings を削る
#!/usr/bin/env perl6
use strict;
while (<>) {
print;
}
実行した結果
$ ./cat.pl helloworld
===SORRY!=== Error while compiling /home/ajishixo/dev/perl6/./cat.pl
Unsupported use of <>; in Perl 6 please use lines() to read input, ('') to represent a null string or () to represent an empty list
at /home/ajishixo/dev/perl6/./cat.pl:5
------> while (<⏏>) {
ダイアモンド演算子も無くなった様子。
ダイアモンド演算子をlinesに書き換え
#!/usr/bin/env perl6
use strict;
while (lines) {
print;
}
$ ./cat.pl helloworld ===SORRY!=== Error while compiling /home/ajishixo/dev/perl6/./cat.pl Unsupported use of bare "print"; in Perl 6 please use .print if you meant $_, or use an explicit invocant or argument, or use &print to refer to the function as a noun at /home/ajishixo/dev/perl6/./cat.pl:6 ------> print⏏;
print;はprint $_;の$_を省略した形でしたが、$_.print;として$_を省略し.printという形になるのですね。
printを.printに書き換え
#!/usr/bin/env perl6
use strict;
while (lines) {
.print;
}
実行すると
$ ./cat.pl helloworld Use of uninitialized value of type Any in string context. Methods .^name, .perl, .gist, or .say can be used to stringify it to something meaningful. in block <unit> at ./cat.pl line 6 Use of uninitialized value of type Any in string context. Methods .^name, .perl, .gist, or .say can be used to stringify it to something meaningful. in block <unit> at ./cat.pl line 6
stringのコンテキストでAny型の初期化されていない値が使われているとのこと。
Any型とはなんぞや、ということで先ほど入れたp6docに尋ねてみる。が、イマイチ分からず。。
.sayの使用をすすめられたので書き換える。
printをsayに書き換え
#!/usr/bin/env perl6
use strict;
while (lines) {
.say;
}
実行すると
$ ./cat.pl helloworld (Any) (Any)
またもAny。。
linesの戻り値が気になるのでp6docに尋ねてみる。
$ p6doc -f lines
We have multiple matches for 'lines'
Type::Cool.lines Type::Str.lines
Type::Supply.lines Type::IO::Handle.lines Type::IO::Socket::INET.lines
今回はファイルの読み込みなので Type::IO::Handle.lines を選ぶ。
$ p6doc -f Type::IO::Handle.lines
method lines
method lines($limit = Inf)
Return a lazy list of the file's lines read via get, limited to $limit
lines. The new line separator (i.e., $*IN.nl-in) will be excluded.
my @data;
my $data-file = open 'readings.csv';
for $data-file.lines -> $line {
@data.push($line.split(','))
}
分からん。
紆余曲折し、以下の記述にたどり着く。
$ p6doc variables
// 略
Calling a method on $_ can be shortened by leaving off the variable name:
.say; # same as $_.say
m/regex/ and /regex/ regex matches and s/regex/subst/ substitutions work on
$_:
say "Looking for strings with non-alphabetic characters...";
for <ab:c d$e fgh ij*> {
.say if m/<!alpha>/;
}
whileをforに書き換え
#!/usr/bin/env perl6
use strict;
for (lines) {
.say;
}
実行して無事成功。
$ ./cat.pl helloworld Hello World $ cat helloworld | ./cat.pl Hello World
拡張子を変更
$ mv cat.pl cat.p6
おわりに
なぜwhileではダメでforなら良かったのかはp6doc controlを読んでみたけど分からず。
今後の使用で理解していこう。
ubuntu 14.04 から ATERM WG1800HP2 のUSBストレージにつながらない不具合を解消
以前に上手く使えていたのにいつのまにかパスワードが通らなくなってしまっていた。
iPhoneの Remote File Manager Free からは接続できているので、クライアントである Ubuntu 側の問題であると判断。
smbclientコマンドを実行した結果、以下のような出力があった。
$ smbclient //ATERM-HOGE/Fuga -Uuser Enter user's password: Server does not support EXTENDED_SECURITY but 'client use spnego = yes and 'client ntlmv2 auth = yes' session setup failed: NT_STATUS_ACCESS_DENIED
spnegoで調べたところ、下記資料が見つかったので、/etc/samba/smb.confを修正。
smbclientでWindows 7に接続しようとするとsession setup failed: SUCCESS - 0:ほぬほぬの足跡:So-netブログ
# [global]表記直下に追記 client lanman auth = Yes client ntlmv2 auth = No client use spnego = No
無事にアクセスできた。
さくらのVPS上でdocker -dを実行するために四苦八苦
dockerをインストールするのは簡単。
docker -dを実行しようとするとkernelのバージョンが合わないとのこと。
対処として、kernelのバージョンアップを行うか、VPSなのでkernelバージョンの合うOSに入れ替えるかのどちらかが選べたが、行ったことが無いkernelバージョンアップを選択。
CentOS6.3をLinuxカーネル3.6にアップデートしてみました(カーネル再構築)|リナックスマスター.JP 公式ブログ
上記を参考に 3.19.8 を入れた。
さーてdockerは動くかな、と試してみると今度はiptablesのバージョンが合わないということなので、以下を参考に作業。
Ubnutu 14.04 LTSで最新版のiptablesを使う | ビットログ
libmnl, libnftnlもビルドしつつpkg-configやalternativesなんてものがあることを知る。
alternativesについては下記を参考にした。
replace centos 6.x iptables · GitHub
そこでdocker -dを実行すると、また問題が発生。iptables で nat が無効になっていたようなのでkernelを再度ビルド。
make oldconfig のログを読み返すと、確かに新しい設定として検出されていました。ええ、Enter キーを長押しにしていたので気づきませんでしたとも。こんなの気付かないよなぁ・・。
共感しました。でもって参考にしつつmake menuconfigがうまく動作しなかったので愚直に.configを手修正しました。
もいちどdocker -dをして再度問題発生。
rhel6 - Docker on RHEL 6 Cgroup mounting failing - Stack Overflow
grub.confを編集してrebootしてもうまく行かず。
Dockerで`Error: cannot mount hugetlb to /cgroup/hugetlb`と言われた時の対処法 - Qiita
上記リンク先と同様にmemoryに関する行をコメントアウトして `$ sudo /etc/init.d/cgconfig restart` して無事起動。
ようやく`docker -d`も成功。
長かったー。