〜2013年12月上旬〜
そんなAndroid端末があったりする。
shell@android:/ $ /data/local/tmp/busybox sh sh: precmd: Permission denied shell@android:/ $ type precmd precmd: not found sh: precmd: Permission denied shell@android:/ $ date Tue Nov 26 03:33:51 GMT 2013 sh: precmd: Permission denied
ちょっと前のログだが、いったい何が原因なのか。precmdなのでPS1が怪しい。
shell@android:/ $ echo $PS1
$(precmd)$USER@$HOSTNAME:${PWD:-?} $
なるほど、これか。しかしなぜnot foundじゃなくPermission deniedなのか。
/system/bin/shの正体はなにかと調べたらmkshだった。
というわけで/etc/mkshrcが起動時に読み込まれる。
shell@android:/ $ cat /etc/mkshrc
# Copyright (c) 2010
# Thorsten Glaser <t.glaser@tarent.de>
# This file is provided under the same terms as mksh.
#-
# Minimal /system/etc/mkshrc for Android
: ${TERM:=vt100} ${HOME:=/data} ${MKSH:=/system/bin/sh} ${HOSTNAME:=android}
: ${SHELL:=$MKSH} ${USER:=$(typeset x=$(id); x=${x#*\(}; print -r -- ${x%%\)*})}
if (( USER_ID )); then PS1='$'; else PS1='#'; fi
function precmd {
typeset e=$?
(( e )) && print -n "$e|"
}
PS1='$(precmd)$USER@$HOSTNAME:${PWD:-?} '"$PS1 "
export HOME HOSTNAME MKSH PS1 SHELL TERM USER
alias l='ls'
alias la='l -a'
alias ll='l -l'
alias lo='l -a -l'
for p in ~/.bin; do
[[ -d $p/. ]] || continue
[[ :$PATH: = *:$p:* ]] || PATH=$p:$PATH
done
unset p
: place customisations above this line
precmdはfunctionだったわけね。
あとなぜかPS1までexportされていた。これが原因か。
しかしなぜPermission deniedになるのか?
PATHに設定されているディレクトリのpermissionを見てみる。
shell@android:/ $ (IFS=:; for i in $PATH; do ls $i/precmd; done) /sbin/precmd: Permission denied /vendor/bin/precmd: No such file or directory /system/sbin/precmd: No such file or directory /system/bin/precmd: No such file or directory /system/xbin/precmd: No such file or directory
なるほど。/sbinのせいか。
shell@android:/ $ ls -ld /sbin drwxr-x--- root root 1970-06-20 22:56 sbin
これじゃ無理だ。
まとめると、/system/bin/shはmkshで/etc/mkshrcを起動時に読み込む。
そこでPS1が設定されてexportもされる。precmdはfunctionなので見つかる。
この状態でbusybox shを実行するとPS1がそのまま引き継がれて、
プロンプトを表示する際にprecmdが実行される。
busybox shは権限がないと警告を表示するようで、
/sbinが0750だとアクセスできない、と。
Nexus7ではexport PS1してないので、そんな状態にはならない。
で試しに手でやってみると再現した。
shell@grouper:/ $ export PS1 shell@grouper:/ $ /data/local/tmp/busybox sh sh: precmd: Permission denied shell@grouper:/ $
300通ほど。このあたりで落ち着いてるね。
androidのバージョンが上がるごとにinputコマンドでできることが増えている。
% adb shell getprop ro.build.version.release; adb shell input
4.0.4
usage: input [text|keyevent]
input text <string>
input keyevent <event_code>
4.0.4ではこんなもんだったが、4.2.2ではkeyeventは名前でも指定できる。
% adb shell getprop ro.build.version.release; adb shell input
4.2.2
usage: input ...
input text <string>
input keyevent <key code number or name>
input [touchscreen|touchpad] tap <x> <y>
input [touchscreen|touchpad] swipe <x1> <y1> <x2> <y2>
input trackball press
input trackball roll <dx> <dy>
わざわざKEYCODE_1=8とかして$KEYCODE_1で参照してたがその必要もなくなっていた。
あとtapとswipeは便利すぎる。
Kitkatではkeyeventに--longpressがあるってことは長押しにも対応している?
% adb shell getprop ro.build.version.release; adb shell input
4.4
Usage: input [<source>] <command> [<arg>...]
The sources are:
trackball
joystick
touchnavigation
mouse
keyboard
gamepad
touchpad
dpad
stylus
touchscreen
The commands and default sources are:
text <string> (Default: touchscreen)
keyevent [--longpress] <key code number or name> ... (Default: keyboard)
tap <x> <y> (Default: touchscreen)
swipe <x1> <y1> <x2> <y2> [duration(ms)] (Default: touchscreen)
press (Default: trackball)
roll <dx> <dy> (Default: trackball)
+xterm_clipboardとか+clipboardになってれば"*pでok。:pu *でもいい。
set cb=unnamedにすればクリップボードが共有されるのでpだけでいける。
+とかunnamedplusにしたほうがいいときもあるが。
この状態でUbuntuからSynergy経由でCygwinのvimへペーストなんてのも簡単にできて便利。
Ubuntu側のvimで5yyしてCygwin側のvimでpとか。
busyboxにあるコマンドはサブセットなんじゃないか漠然と思ってしまうが、
結構がんばっている。awkにはstrftimeもある。
% busybox awk 'BEGIN{print strftime("%F %T")}'
2013-12-06 01:40:21
% mawk 'BEGIN{print strftime("%F %T")}'
mawk: line 2: function strftime never defined
あとなぜかandだのorだのビット演算もできるようで。
ソース見たらgawk並に関数がそろっていた。
"\3and" "\5compl" "\6lshift" "\2or"
"\6rshift" "\3xor"
"\5close" "\6system" "\6fflush" "\5atan2" /* BUILTIN */
"\3cos" "\3exp" "\3int" "\3log"
"\4rand" "\3sin" "\4sqrt" "\5srand"
"\6gensub" "\4gsub" "\5index" "\6length"
"\5match" "\5split" "\7sprintf" "\3sub"
"\6substr" "\7systime" "\10strftime" "\6mktime"
"\7tolower" "\7toupper" NTC
"\7getline" NTC
"\4func" "\10function" NTC
"\5BEGIN" NTC
"\3END"
おお、gensubが使えるのか。
% gawk 'BEGIN{a="XYZ"; print gensub(/(.)(.)(.)/, "\\3\\2\\1", 1, a), a}'
ZYX XYZ
% busybox awk 'BEGIN{a="XYZ"; print gensub(/(.)(.)(.)/, "\\3\\2\\1", 0, a), a}'
ZYX XYZ
以前は適当にwebrickでサーバ立てて簡単にSony Readerでepubをダウンロードできたが、
いつのまにか失敗するようになってしまった。
原因はmime typeのようで、application/octet-streamじゃだめみたい。
application/epub+zipにする必要がある。
% ruby -run -e help httpd Run WEBrick HTTP server. ruby -run -e httpd -- [OPTION] DocumentRoot --bind-address=ADDR address to bind --port=NUM listening port number --max-clients=MAX max number of simultaneous clients --temp-dir=DIR temporary directory --do-not-reverse-lookup disable reverse lookup --request-timeout=SECOND request timeout in seconds --http-version=VERSION HTTP version -v verbose
やっぱないよなあ。追加するか。でもhashだから指定しづらい。
setup("", "BindAddress=ADDR", "Port=PORT", "MaxClients=NUM", "TempDir=DIR",
"DoNotReverseLookup", "RequestTimeout=SECOND", "HTTPVersion=VERSION", "MimeTypes=TYPE") do
として、
opt = options[:MimeTypes] and options[:MimeTypes] = WEBrick::HTTPUtils::DefaultMimeTypes.merge(Hash[*opt.split])
を追加して
% ruby -run -e httpd -- --port=8080 --mime-types='epub application/epub+zip' .
とすればいいか。
コマンドがなかったら、これをインストールしろよ的なあれがzshにも欲しくて
source /etc/zsh_command_not_found
を.zshrcに入れてみたが、本当に間違えたときにやたらと時間がかかって、挙句の果てに
% foo コマンド 'foo' は見つかりませんでした。もしかして: コマンド 'goo' - パッケージ 'goo' (universe) コマンド 'fio' - パッケージ 'fio' (universe) コマンド 'zoo' - パッケージ 'zoo' (universe) コマンド 'fgo' - パッケージ 'fgo' (universe) コマンド 'fop' - パッケージ 'fop' (main) コマンド 'fox' - パッケージ 'objcryst-fox' (universe) コマンド 'fog' - パッケージ 'ruby-fog' (universe) コマンド 'xoo' - パッケージ 'xoo' (universe) zsh: command not found: foo zsh: exit 127 foo
とか出てきて困惑している。消そう。
IFTTTからのメールで気づいた。確認してみたら12/2からtwitterのbotが止まっていた。
RSSもすでに404でやっぱこっそり終了ということなんだな。
しかし困ったねえ。Yahoo Pipesか?
というわけで、
こんなのをYahoo! Pipesで作ってみたけど、IFTTTが拾ってくれない。
一発だけ通ったきりでその後音沙汰なし。
checkも通ってるし何が悪いんだろう。
アメダスのページって当然固定なのでRSSのlinkも固定にしておいたら、
GUIDが変化しなくて更新されてないとみなされていた。
つまり無理矢理にでもURLを変える必要がある。
以前のアメダスRSSを確認してみたらやはり一見無駄とも思えるパラメータがついていた。
というわけでなんかつけないといけないわけで、一番簡単なタイムスタンプをつけてみた。
Date Builderでparse可能な文字列を指定する。
User Input Modulesを見るとnowが使えるので現在時もok。
あとはDate Formatterを使って?rss%F-%TをlinkのURLに追加してみた。
が、これではアクセスする度にURLが変わってしまいGUIDも変化してしまう。
1時間1度しか更新されないわけで?rss%F-%Hにしないとまずい。
いやいや、実際に更新されるのは毎時ぴったりじゃないので%Hでもまずい。
tableに観測した時刻があるのでこれを使うことにしてやっとできあがり。
これでIFTTTも拾ってくれるようになった。