Shell
# PDF
~~~
$ wget --spider --force-html -r -l2 "vitalik.ca" 2>&1 | grep "https" > hoge.txt
$ cat url-list.txt | while read line ; do /Applications/Chromium.app/*/*/Chromium --headless --print-to-pdf="$(echo $line | sed -e 's/https\:\/\/vitalik\.ca\/general\///' -e 's/\//-/g' -e 's/html/pdf/')" "$line" ; done ; ./page2pdf.sh
~~~
# Devices
## list Devices
~~~sh
@ osx
$ diskutil list @osx
@ linux
$ fdisk -l
$ mount -l
~~~
# Network
program | obsoleted by
------------|---------------
arp | ip neigh
ifconfig | ip addr
ipmaddr | ip maddr
iptunnel | ip tunnel
route | ip route
nameif | ifrename
mii-tool | ethtool
## ipconfig
~~~sh
# ifconfig | grep flags
...
lo0: flags=8049 mtu 16384
gif0: flags=8010 mtu 1280
en0: flags=8863 mtu 1500
...
~~~
## ifconfig
~~~sh
# ipconfig getpacket lo0
# ipconfig getpacket gif0
# ipconfig getpacket en0
... ## if en0 is connected some information is listed
~~~
## nmap
nmap searches the state how an IP address serves in the Internet or Local Network.
~~~
> /& proxychains &/ nmap -A -p 1-22 (TARGET'S IP)
~~~
22/tcp open ssh
hydra is said to be a brute force attacking tool. To prevent this you can ban the IPs which have attacked you, and before that you have to be sure that your ssh username is long enough to be unpredictable.
~~~sh
> hydra -l (USER TO LOG IN AS) -x 4:10:aA 192.168.8.101 ssh
~~~
# nc (netcat)
~~~
On ‘server’ side:
$ rm -f /tmp/f; mkfifo /tmp/f
$ cat /tmp/f | /bin/sh -i 2>&1 | nc -l 127.0.0.1 1234 > /tmp/f
On ‘client’ side:
$ nc host.example.com 1234
$ (shell prompt from host.example.com)
By doing this, you create a fifo at /tmp/f and make nc listen at port 1234 of
address 127.0.0.1 on ‘server’ side, when a ‘client’ establishes a connection
successfully to that port, /bin/sh gets executed on ‘server’ side and the shell
prompt is given to ‘client’ side.
When connection is terminated, nc quits as well. Use -k if you want it keep
listening, but if the command quits this option won't restart it or keep nc
running. Also don't forget to remove the file descriptor once you don't need it
anymore:
$ rm -f /tmp/f
~~~
# bc
~~~sh
echo {1..100}" +" 0 | bc
# Add up all the numbers from 1 to 100 using a brace expansion trick.
~~~
# pgrep
~~~sh
$ pgrep sshfs
740
$ kill 740
~~~
# function arguments
~~~sh
print_str() {
echo "$1, $2 !"
}
print_str "Hello" "World"
// Hello, World !
~~~
e.g. function
~~~sh
jstdate(){
LANG=ja_JP.UTF-8 date
}
engdate(){
LANG=en date
}
$ date // 2014年 9月 25日 木曜日 20:36:48 JST
$ jstdate // 2014年 9月 25日 木曜日 20:36:52 JST
$ engdate // Thu Sep 25 20:38:01 JST 2014
~~~
# zcat
zcat : cat zipped text
# nkf
~~~sh
$ cat 文字化け.txt | nkf -wLux
-w : convert to UTF-8
-Lu : convert to LF ( UNIX 改行 code )
-x : 半角カナを全角にしない
~~~
~~~sh
$ cat utf8.txt | nkf -sLwx
-s : convert to Shift-JIS
-Lw : convert to (CRLF)
~~~
cf. iconv
~~~sh
$ iconv -f SHIFT-JIS -t UTF-8 < inputFile > outputFile
~~~
# rev
~~~
$ cat hello.txt
hello world
~~~
~~~
rev < hello.txt
dlrow olleh
~~~
`<` : 標準入力
# zcat
# uniq
uniq the same line into a line
~~~
$ cat file.txt
_
hoge
foo
hoge
hoge
foo
$ cat file.txt | uniq -c
1 _
3 hoge
2 foo
~~~
# sed 's; ; ;'
~~~
$ cat /etc/shells | grep -v '#'
/bin/bash
/bin/csh
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh
$ cat /etc/shells | grep -v '#' | sed 's;.*/;;'
bash
csh
ksh
sh
tcsh
zsh
~~~
変数の文字列を先頭大文字にしたり全て大文字/小文字にしたりするのに sed は使わない。
~~~
$ os=linux; echo ${os^}
Linux
$ os=linux; echo ${os^^}
LINUX
$ os=LinuX; echo ${os,}
linuX
$ os=LinuX; echo ${os,,}
linux
$ os=LiNuX; echo ${os~~}
lInUx
$ os=Linux; echo ${os//inu/umi}
Lumix
~~~
# `cat -n`
: display line number
# `df` : disk free
- display free space of disk
# 3 2 1
~~~
VLIST='1 2 3'
t=; for val in $VLIST; do t="$val $t"; done
for val in $t
do
echo "$val"
done
~~~
# `curl`
* curl は標準出力となる
* wget ファイルとして保存
~~~sh
curl localhost:4000 |grep someword
~~~
## HTTP request
jq のインストール
~~~
curl localhost:8080/api/json | jq
curl localhost:8080/api/json -o response // save output to a file
curl localhost:8080/api/json -o // save output to a file with a default name
curl localhost:8080/api/json -O -# // show ####### 100.0%
curl -s localhost:8081/api/json // exclude err but not displayed
curl -Ss localhost:8080 // -S : shows error
~~~
## HEADER
~~~
curl -I localhost:8080/api/json // get HEADER only
~~~
## DUMP
~~~
curl --trace
curl --trace-ascii
~~~
~~~
curl --trace-time
~~~
jenkins を使い認証サービスを curl で使うことができる
# `find`
~~~
$ find [path] [condition] [action]
~~~
~~~
-type filetype
f : normal file
c,d : directory
l : linking file
-print : display the full path of files
~~~
e.g. show the contents of files with name "hoge"
~~~
$ find ./ -type f -print | grep 'hoge' | xargs cat
~~~
# `xargs`
標準入力からコマンドラインを作成し、それを実行する
# `grep`
ファイルから文字列を検索する。grep の後に検索したい文字列を指定する
# `|` (pipe)
e.g.
~~~
> ls // a a.c b b.c c c.c
> mv $(ls | grep -v ".c") ../mybin/
> ls // a.c b.c c.c
~~~
`*.c` files removed with -v option
# rename
e.g.
~~~
> ls
enshu1.c
enshu2.c
> rename 's/enshu/ex/' ./*
> ls
ex1.c
ex2.c
~~~
# call functions from a file
- `return(exit) (0~255)` : finish the function call
- `echo` : output strings to the shell
e.g.
~~~
--a.sh---
#!/bin/sh
. ./b.sh ## Load the file "b.sh"
val=$(hoge)
echo $?
echo $val
--b.sh---
#!/bin/sh
hoge(){
echo "Hello, from hoge!"
exit 251
}
~~~
~~~
$ ./a.sh
251
Hello, from hoge!
~~~
# Shell
## shell classification
- outer command : executable files
- builtin command : defined and used only in the shell
- alias
- `type` : alias -> builtin -> outer の順に優先して表示
- `type -a` : 全部を表示
- `which` : display only outer command
e.g.
~~~
$ type set
set is a shell builtin
$ which set
/usr/bin/which: no set in (/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/xxx/bin) #=>
~~~
# wait
wait for bg process to exit
~~~
$ sleep 10 &
$ wait
[1]+ Done sleep 10
$
~~~
# `-e` option
終了ステータスが0以外だった場合はただちにシェルを終了する
~~~
$ sh -e
> true
> false //終了ステータスが1
$
~~~
シェル実行中一時的に無効化したい場合
~~~
$ sh -e
> set +e // -e option を無効化
> true
> false // 終了しない
> set -e
> true
> false
$
~~~
# env
1. 環境変数の一覧表示
2. 環境を指定して実行
# `set -- `
位置parameter を設定
~~~
$ cat s16.sh
#!/bin/sh
echo $1 $2 $3 $4 $5
set -- a b c d e
echo $1 $2 $3 $4 $5
$ ./s16.sh 1 2 3 4 5
1 2 3 4 5
a b c d e
$
~~~
この機能は繰り返し構文で同じ処理を実施する場合に使われる。
繰り返し構文の最初の段階で毎回`set -- $(eval echo \$any_vars$i)`
のようにして値を設定し、繰り返し構文の中では$1や$2で値にアクセスできる。
for 文に代入できる変数は1つしかないので、この仕組みを使うと
複数の変数を使用できるようになる。
# set (unset)
- 組み込みシェル変数を表示する
- 変数の一覧表示
unset 変数の削除
~~~
$ set
Apple_PubSub_Socket_Render=/tmp/launch-8mNEZ5/Render
BASH=/bin/bash
...
OPTERR=1
OPTIND=1
OSTYPE=darwin13.4.0
PATH='/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:$PATH:/usr/local/apache-maven-3.2.2/bin:'
PIPESTATUS=([0]="0")
PPID=36585
PROMPT_COMMAND='update_terminal_cwd; '
PS1='\h:\W \u\$ '
PS2='> '
PS4='+ '
...
~~~
# `getopts`: builtin command
e.g.
~~~
$ cat opt.sh
#!/bin/sh
while getopts cs:n:a:wVh?v opt // : は引数をとることを意味する
do // 引数は $OPTARG に格納
case "$opt" in
c) colordiff_mode=true ;;
s) waitsec=$OPTARG ;;
n) colorhistnum=$OPTARG ;;
a) alert_mode=true
alertcommand=$OPTARG ;;
w) fitwindowwidth=false ;;
V) header_mode=true ;;
h|\?) echo "$usage_msg" 1>&2
exit 0 ;;
v) echo "topless version $version"
exit 0 ;;
esac
done
shift $(($OPTIND - 1 )) // 引数の読み込み位置を初期化
~~~
`OPTARG` has arguments
# declare
: 環境変数の表示
# exit
: シェルを終了
# exec
: プロセスの置き換え
- execve システムコールに相当し、
- 自身を置き換えて実行する為、シェルはそこで途切れる
- ラッパースクリプトなどで、本来実行したいとしているソフトウェアを実行するときに使われる
~~~
---s14.sh---
#!/bin/sh
exec /usr/bin/printf "done\n" //新しいシェルへ移動
/usr/bin/printf "done2\n" //この行は実行されない
------------
$ ./s14.sh
done
~~~
# `:`
~~~
$ echo $b //
$ echo ${b:-B} // B (変数に情報は保存しない)
$ echo $b //
----------------------
$ echo $b
$ echo ${b:=B} // B (&& 変数に情報を格納)
$ echo $b // B
~~~
## `:` : scilently
~~~
> : ${a:=123} // first : deal errors without output, so do scilently
~~~
## `${name:-value}`
`if ($name is null) value else $name`
~~~
> name=hello
> echo ${name:-world}
hello
> name=
> echo ${name:-world}
world
~~~
## `${name:+value}`
`if ($name is null) $name else value`
## `${name:=value}`
`if ($name is null) name=value && $name else $name`
## `${name:start:length}`
~~~
${name:start}
${name:start:length}
~~~
e.g.
~~~
> x=catsle
> ${x:3:2}
( ) (@@) ( ) (@) () @@ O @ O @ O
(@@@)
( )
(@@@@)
( )
++ +------ ____ ____________________ ____________________
|| |+-+ | | \@@@@@@@@@@@ | ___ ___ ___ ___ | | ___ ___ ___ ___ |
/---------|| | | | \@@@@@@@@@@@@@_ | |_| |_| |_| |_| | | |_| |_| |_| |_| |
+ ======== +-+ | | | |__________________| |__________________|
_|--/~\------/~\-+ |__________________| |__________________| |__________________|
//// O========O_/ (O) (O) (O) (O) (O) (O)
> ${x:0:3}
hello
hello
~~~
# cd
~~~java
/*
** this is a part of
** the sourceCode of
**
**
** COMMAND "cd" in ash
**
**
** writing about updatepwd()
**
**「移動可能か調査してから移動する」
** を記述したソース
*/
static void
updatepwd(char *dir)
{
hashcd(); //update command hash table
if (prevdir)
ckfree(prevdir);
prevdir = curdir;
curdir = dir ? savestr(dir) : null;
setvar("PWD", surdir, VEXPORT);
setvar("OLDPWD", prevdir, VEXPORT);
}
~~~
# 展開
文字列展開の優先順位
1. チルダ展開
2. parameter 展開
3. コマンド置換
4. 算術演算
5. IFS (Input Field Separator)
6. パス名展開
7. クウォートの削除
## `*` `?` : パス名展開
~~~sh
$ l /usr/l*/lib*
/usr/lib/libACSClient.dylib* /usr/lib/libecpg_compat.dylib@
...
~~~
? : 1 character
~~~sh
$ ls ?.txt
a.txt
5.txt
~~~
## "" : フィールドセパレータ分割
~~~sh
$ a=$(printf " a b\n c \n\t ")
$ echo $a // 展開結果にはIFS変数の分割に従って展開
a b c
$ echo "$a" // "" でくくると文字列として展開
a b
c
~~~
## `%` `%%` / `#` `##` : parameter展開
- %と%%は右から削除
- #と##は左から削除
~~~sh
$ ENV=/home/sh/.shrc
$ echo $ENV // /home/sh/.shrc
$ echo ${ENV%e*} // /hom
$ echo ${ENV%.*} // /home/sh/
$ echo ${ENV#*/} // home/sh/.shrc
$ echo ${ENV##*/} // .shrc
$ echo ${ENV%h*} // /home/sh/.s
$ echo ${ENV%%h*} // /
~~~
## コマンド置換
$( ) で囲まれた文字が対象
## 算術展開
$(( )) で囲まれた文字列が対象
## チルダ展開
| | |
| ------------- | -------------------- |
| ~ | $HOME を表す |
| ? | 任意の一文字 |
| * | 任意の文字列 |
| [文字列] | 文字列内のどれか 1 文字 |
| [^文字列] | 文字列内の文字以外の文字 |
## ブレース展開 (bash~)
~~~
$ touch {1..3}{0..9}番目の{書類,個人情報}.txt
$ l
10番目の個人情報.txt 20番目の個人情報.txt 30番目の個人情報.txt
10番目の書類.txt 20番目の書類.txt 30番目の書類.txt
11番目の個人情報.txt 21番目の個人情報.txt 31番目の個人情報.txt
11番目の書類.txt 21番目の書類.txt 31番目の書類.txt
….
~~~
## cat << EOF
~~~
$ cat << EOF >a.txt
>this is a pen
>i am tom
>EOF
$ cat a.txt
this is a pen
i am tom
~~~
# operators
- 単項演算子: ! , ~ , + , -
- 二項演算子: * , / , %, +, -, <, >, <<, >>, <=, >=, ==, !=, &, ^, |, &&, ||
- 代入演算子: = , +=, -=, * =, /=, %=, <<=, >>=, &=, ^=, |=,
- 条件演算 : ? , :
# special variable
* $0 : 第0引数 つまりシェル名(コマンド)
* $#:引数number
* $* :
* $@
* $?
* $$
# `>` / `<` : output / input
~~~
2>&1 :「 標準エラー出力 」を「 標準出力 」と同じ場所に出力
1>&2 :「 標準出力 」を「 標準エラー出力 」と同じ場所に出力
~~~
copy of file descriptor
~~~sh
2> : 2 is "descriptor number"
> , 1> : descriptor number is 1
~~~
e.g.
~~~sh
$ awk '$1>>1' // output Syntax error
awk: syntax error
$ awk '$1>>1' 2> err
$ cat err
awk: syntax error
~~~
# read (builtin)
~~~sh
$ cat data
1
2
3
4
5
6
7
8
9
~~~
最後にデータを入力する
~~~sh
$ while read a
> do
> i=$(($i + $a))
> done < data
$ echo $i
45
~~~
パイプで渡すと失敗する
~~~sh
$ cat data |
> while read a
> i=0
> do
> i=$i+1
> done
^C
$ echo $i //スコープ外なのでnull
~~~
# シェルとカーネル
通常のソフトは直接システムコールをたたくことはない
シェルは直接システムコールを積極的にたたくソフトウェア
シェルのソースコードを読むとその辺りがよくわかる
ashまたはdashがとっかかりとしてはよい
リダイレクト:シェルの入出力機能
ashの実装から:
~~~
//nodetypes (ファイルリダイレクト裏に関するリスト)
NTO nfile # fd > fname
NFROM nfile # fd < fname
NFROMTO nfile # fd <> fname
NAPPEND nfile # fd >> fname
NCLOBBER nfile 1# fd >| fname
NTOFD ndup # fd <& dupfd
NFROMFD ndup # fd >& dupfd
NHERE nhere # fd << \!
NXHERE nhere # fd << !
~~~
//redir.c (リダイレクトリを処理している部分)
~~~c
case NTO:
if (Cflag) {
fname =redir->nfile.expfname;
if(stat(fname, &sb) == -1){
if((f = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666)) < 0)
error("");
} else if (!S_ISREG(sb.st_mode)){
if ((f = open(fname, 0_WRONTY, 0666)) < 0)
error("");
if (fstat(f, &sb) != -1 && S_ISREG(sb.st_mode)) {
close(f);
error("");
}
} else
error("");
goto movefd;
}
...
movefd:
if (f != fd) {
if (dup2(f,fd) == -1) {
e = errno;
close(f);
error("");
}
close(f);
}
break;
//例外処理を除いて書くと
case NTO:
f = open(fname, O_WRONTY, 0666);
dup2(f,fd);
close(f);
~~~
# shell declaration statement
~~~sh
#!/bin/sh
~~~
# null file pointer
cleanup file
~~~sh
/dev/null > filename
~~~
~~~sh
: > filename
~~~
でも削除できる
e.g. abc.logを圧縮し、元ファイルを削除する
~~~sh
#!/bin/sh
cp -p abc.log abc.log.bak
gzip abc.log.bak
cat /dev/null > abc.log
~~~
# shells
~~~sh
$ ls -il /bin/ | grep sh
11153 -r-xr-xr-x 1 root wheel 1228240 May 13 03:55 bash*
334486 -rwxr-xr-x 2 root wheel 357984 May 13 04:00 csh*
291606 -r-xr-xr-x 1 root wheel 1315248 May 13 04:00 ksh*
11154 -r-xr-xr-x 1 root wheel 1228304 May 13 03:55 sh*
334486 -rwxr-xr-x 2 root wheel 357984 May 13 04:00 tcsh*
335114 -rwxr-xr-x 1 root wheel 530320 May 13 04:00 zsh*
~~~
## dash
- dash : debian's default shell
- ash : older one
## bash
- ashにくらべ重いが
- 「ブレース展開」という拡張機能がある
## ksh
ksh だけの機能
~~~
$ cat <<< inline_here_documents
inline_here_documents
~~~
## csh
switch文とfor文の記述の仕方が違う
~~~ sh
# csh
# set prompt = ""
~~~
~~~
foreach i (0 1 2 3)
echo smartctl -a /dev/ada$i
end
~~~
~~~
switch ("a")
case "a"
echo a
breaksw
case "b"
echo b
breaksw
default:
echo default
breaksw
endsw
~~~
## bourne shell (sh)
- `~/.bashrc`にその他の設定を記述
- `~/.bash_profile`に基本設定と
~~~
sh
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
~~~
とし、ログイン時に.bashrcを読み込む
## chsh
change shell command
~~~sh
$ chsh
Changing shell for … => editorが起動
~~~
# mdls
:メタデータを表示
~~~sh
$ mdls a.jpg //jpegのメタデータを表示
~~~
# mdfind
:メタデータの検索=Spotlight検索
# tee
~~~sh
command|tee
$ cal | tee cal.txt
// カレンダーの出力結果をteeコマンドにわたし、teeによりファイルに書き出される
~~~
# locate
:指定した文字列を含むパスの検索
~~~sh
$ sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.locate.plist
// データベース(defaultで毎週土曜午前3時15分に更新)の作成
$ sudo /usr/libexec/locate.updated //手動更新
$ ls -lh /var/de/locate.database //データベースの場所
~~~
# ()
: grouping
:(括弧内はローカル変数として処理される)
~~~sh
$ ( command )
$ echo 今年は$(date "+%Y")年です // 今年は2014年です
~~~
## variable = value
~~~sh
$ osname = “Mac OS X”
$ echo $osname // Mac OS X
~~~
## { }
:wrap variable Name
~~~sh
$echo "${OS}OS X"
MACOS X
~~~
## quotation
~~~ sh
$ OS = MAC
$ echo “$OS” // MAC
$ echo '$OS' // $OS
$ set `cal`
$ echo $1 // September
$ echo $2 // 2014
$ echo $@ // September 2014 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 ...
$ echo $# // 39 => the # of args
~~~
## export VARIABLE
:変数を環境変数にする(scope)
## `chmod` / `chown` / `chgrp`
~~~sh
ls -l
-rw-r-x—
-rwxrwxrwx
~~~
~~~
owner group other
rwx rwx rwx
111 111 111 ←二進数
7 7 7
~~~
~~~
$ chmod 777 filename
~~~
-R : recursive : サブディレクトリ以下にも同様の処理を展開する
~~~
$ chmod -R 400 filename
~~~
~~~
chown :オーナーを変更する
chgrp :所有グループを変更する
~~~
## ACLs
UNIX の conventional permission では
- owner,
- group,
- other の三段階でしかアクセス制御できない
ACLs : Access Control Lists
~~~ sh
$ ls -l
drwx———@
drwxrwxrwx@
drwxr-xr-x
~~~
最後に@や+がついているとACLsが設定されている
# job & process
job & process
process is a elementary
job sometimes consists of processes
## `ps`
:プロセス一覧を表示
## `ctlr + z`
:ジョブを一時停止
## `bg`
:ジョブをバックグラウンドにする
~~~ sh
$ bg %ジョブ番号
~~~
## `fg`
:フォアグラウンドジョブに切り替える
~~~ sh
$ fg %ジョブ番号
~~~
kill %jobNo.
kill processNo.
# zsh
## short cut
~~~
Shortcut Action
CTRL + A Move to the beginning of the line
CTRL + E Move to the end of the line
CTRL + _ Undo the last change
CTRL + U clear the entire line
CTRL + K Clear the char @cursor pos
CTRL + W Delete the word in front of the cursor
ESC + [backspace] Delete the word in front of the cursor
~~~
~~~
ALT + D Delete the word after the cursor
CTRL + R Search history
CTRL + G Escape from search mode
CTRL + L Clear
CTRL + S Stop output to screen
CTRL + Q Re-enable screen output
CTRL + C Terminate/kill current foreground process
CTRL + Z Suspend/stop current foreground process
Command Action
!! Execute last command in history
!abc Execute last command in history beginning with abc
!abc:p Print last command in history beginning with abc
~~~
## Special setup for Mac OS X
1. Go to Terminal -> Preferences -> Settings -> Keyboard
2. To enable the use of the ALT or OPTION key, select use option as meta key
3. To enable the CTRL + [left arrow] and CTRL + [right arrow] shortcuts, select
- control cursor left and set it to \033b and
- control cursor right and set it to \033f.
~~~
CTRL + [left arrow] Move one word backward (on some systems this is ALT + B)
CTRL + [right arrow] Move one word forward (on some systems this is ALT + F)
~~~