文書の過去の版を表示しています。
yash
Shell scriptで色々実行しようとしていると、余計な拡張の入ったshellは使いたくなくなる。拡張に依存してPOSIXを忘れてしまうと、マシンごとに異なるshell環境でどハマりをしてしまうからである。
というわけで、POSIX準拠の比較的Primitiveなshellを探し求めてきたわけだが、結局選択できるshellは3種類に絞られてしまった。
: ash ; NetBSDやFreeBSD に付属するshell で、Almquist shellを元にしたもの : dash ; Debian, Ubuntuで採用されているshellで、Almquist shellをdebian Projectで改変したもの : yash ; magicant(WATANABE Yuki)氏が開発したYet Another SHell。一部制限事項を除きPOSIX.1-2008 (IEEE Std 1003.1, 2016 Edition) を全てサポートしているshellで、日本語の情報も十分に提供されている。
本記事では、この yash をMacOS-X BigSur上のtmuxで利用するためのDraftである。
yash
yashの情報は以下を参照のこと
特徴は以下の通り
- 小さい
- POSIX.1-2008準拠
- コマンドライン補完やコマンドラインエディット機能を持つ
- LicenseはGPL… → 個人的には、ここだけ気に入らない。BSDライセンスなら…とも思うが、まぁ、仕方がない。
- Software Development Utilities オプションと C-Language Development Utilities オプションを備えた任意の POSIX.1-2001 環境でビルド・実行できる
- MacにはHomeBrewからInstallできる
yashの設定
yashの環境としては、
- login shellとしては拡張の機能を使いたい
- shell scriptを実行する環境としては、POSIX shellとして動いて欲しい
という2つの条件を満たすように設定する。
.yash_profile
login時に読み込まれるファイル。システムの標準設定を記載する。
yashは、特に指定をしない限り、/etc/profile
や~/.profile
を読み込まない。代わりに、~/.yash_profileを読み込む。
個人的にはこの挙動は気に入らないので、
ln -s ~/.profile ~/.yash_profileして共通にしている。
<code bash .yash_profile>
################################################################################
# Shell Configuration
################################################################################
## Environment Variables
# UNIX Standard Paths
PATH='/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/local/sbin'
# System Specific Paths
[ -d “/usr/local/opt/openssl/bin” ] && export PATH=“/usr/local/opt/openssl/bin:${PATH}”
# Personal Paths
[ -d “${HOME}/bin” ] && export PATH=“${PATH}:${HOME}/bin”
</code>
ここでは、login時にどうしても設定しなければならない最小限の環境変数を設定する。こうすることで、shell scriptを実行する際に怪しい挙動を考えなくて良くなる。
* /usr/local/opt/openssl/bin は、MacOS BigSurにおいて最新版のopensslをコマンドラインから実行するためにこのように設定している。
* /sbin,/usr/sbin,/usr/local/sbin をPATHに入れずに、コマンド起動時に手入力する人もいるが、私は面倒なので、PATHに入れている。
* ~/bin は人によって色々な異論があると思うが、個人的にはscriptが大量にある関係もあって、PATHに加えている。
==== .yashrc ====
.yashrcは、shellがInteractiveモードで起動された場合に実行される(読み込まれる)ファイル。ここに、生活に関係する大量の設定を投入する。
注意点として
* .yashrc は
ln -s ~/.login ~/.yashrcを実行して、全てのshellで共通にする
* yash/ash/dash/bash/zsh 固有の設定はshellの種類を判別して記述する
* yashにおいては、.yash_profileを読み込んだのち、(POSIX非互換モードの場合、)/usr/local/share/yash/initialization配下にあるファイル(特にcommon)を読み込む。その際にPS1を書き換えてしまうので、.yash_profileにPS1など幾つかの設定を記述しても無駄になる。
* 迂闊な設定ミスをすると、Command-line completionやEditor利用中のCtrl-Zが効かなくなるなどの怪しい挙動を示すので注意が必要
などが挙げられる。
<code bash .yashrc>
################################################################################
# Shell Configuration
################################################################################
### Functions
## Common
hup() { (read pid; kill -HUP $pid) </var/run/$1.pid; }
start_tmux() {
TMUX_BIN=`which tmux`
[ ! -x ${TMUX_BIN:-“”} ] && echo “RET” && unset TMUX_BIN && return
TMUX_SESS=`hostname`
TMUX_SESS=“${TMUX_SESS.*}"
[ ! -z ${__TMUX_SESS__:-""} ] && __TMUX_SESS__="${__TMUX_SESS__}"
if [ -z ${TMUX:-""} -a -z ${STY:-""} ]; then
__TMUX_OPTION__=""
if ${__TMUX_BIN__} has-session -t ${__TMUX_SESS__} > /dev/null 2>&1 ; then
__TMUX_OPTION__="attach -t ${__TMUX_SESS__}"
else
__TMUX_OPTION__="new-session -s ${__TMUX_SESS__} ; split-window -h"
fi
${__TMUX_BIN__} ${__TMUX_OPTION__}
fi
unset __TMUX_BIN__ __TMUX_SESS__ __TMUX_OPTION__
}
## for yash
if [ -x /usr/local/bin/yash ]; then
sh() { yash --posix "$@"; }
else
sh() { /bin/sh "$@"; }
fi
## Yash common configuration
if [ ! -z "${YASH_VERSION}" ] ; then
# set -f # -f すると'*'が展開されなくなる
bindkey --emacs '\^L' clear-and-redraw-all # for emacs mode
# POSIX collect modeでは、YASH拡張が使えなくなる
# set -o posixlycorrect
fi
### Personal Environment Variables
# for HomeBrew
export HOMEBREW_GITHUB_API_TOKEN="37edea7e3d75b4a84fb2d913008af7ebef407033"
# Shell Variables.
umask 022
## Environment Variables
EDITOR=vi
for i in lv less more; do which $i 2>&1 > /dev/null && PAGER=`which $i`; done;
## Aliases
alias h='fc -l'
alias j=jobs
alias ll='ls -laFo'
alias l='ls -l'
alias g='egrep -i'
alias man="LANG=C /usr/bin/man"
alias nossh='ssh -o "UserKnownHostsFile /dev/null"'
alias noscp='scp -o "UserKnownHostsFile /dev/null"'
alias svn='LANG=ja_JP.UTF-8 svn'
## Shell command line editing ***WARN***
set -o emacs
( set -o tabcomplete 2>/dev/null ) && set -o tabcomplete # for NetBSD /bin/sh
: ${__HOSTNAME__:=$(uname -n)}
PS1="${__HOSTNAME__.*}”
case `id -u` in
0) PS1=“${PS1}# ”;;
*) PS1=“${PS1}$ ”;;
esac
unset HOSTNAME
## Execute command
[ -x /usr/bin/tset ] && eval $(tset -sQrm 'unknown:?unknown')
[ -f $HOME/bin/goenv.sh ] && . $HOME/bin/goenv.sh
[ -f $HOME/bin/rbenv.sh ] && . $HOME/bin/rbenv.sh
start_tmux
################################################################################
#
# 予約環境変数
# i : for counter
# HOSTNAME : hostname
#
# TMUX_BIN : tmux executable file
# TMUX_OPTION : tmux options
# TMUX_SESS_NAME : tmux session name
#
# PAGER : temporaly pager commands
#
# This .profile is checked under following OSs.
# - MacOS-X BigSur
#
# This .profile is checked under following shells.
# - zsh (5.8)
# - yash (2.51)
# - dash (from HomeBrew)
# - ash (FreeBSD-12.2-p3)
#
# * WARNINGS *
# - dash included in OS-X BigSur is compiled without commandline completion. Must use HomeBrew version.
</code>
これで、個人的に必要になる設定は終わり。
注意点は、start_tmux()。
<code bash start_tmux>
start_tmux() {
TMUX_BIN=`which tmux`
[ ! -x ${TMUX_BIN:-“”} ] && echo “RET” && unset TMUX_BIN && return
TMUX_SESS=`hostname`
TMUX_SESS=“${TMUX_SESS%%.*}”
[ ! -z ${TMUX_SESS:-“”} ] && TMUX_SESS=“${TMUX_SESS}”
if [ -z ${TMUX:-“”} -a -z ${STY:-“”} ]; then
TMUX_OPTION=“”
if ${TMUX_BIN} has-session -t ${TMUX_SESS} > /dev/null 2>&1 ; then
TMUX_OPTION=“attach -t ${TMUX_SESS}”
else
TMUX_OPTION=“new-session -s ${TMUX_SESS} ; split-window -h”
fi
${TMUX_BIN} ${TMUX_OPTION}
fi
unset TMUX_BIN TMUX_SESS TMUX_OPTION
}
</code>
* tmuxは、複数を重なって起動すると幸せにならないので、Hostnameなどを利用したtmux sessionを作成し、必要があればnew-session、なければ attach、それもなければ、tmuxをskipするようにしてある
* 一時利用した環境変数はちゃんと消去する
* どこかで間違って上書きされないように、被らない変数名をつけ、確実にunsetする
* localはPOSIXに存在しないので、利用しない
==== yashのDebugのために必要な幾つかのコマンド ====
*
set -o
* 現在の各種オプションの設定確認
*
set -o poisly-correct
* POSIX互換モードに移行する
* set -o emacs
* emacsモードでの行編集が可能になる
*
local
* local変数を表示する
*
typeset -f''
- 定義されている関数を表示する
終わりに
まだまだ書くべきことはたくさんあるが、ひとまずここまで。