【問題と解答】jus共催 第48回引きこもりもりシェル芸勉強会

Sat Jun 27 16:25:59 JST 2020 (modified: Sat Jun 27 16:25:59 JST 2020)
views: 2912, keywords:プログラミング,勉強会,シェル芸,シェル芸勉強会 この記事は最終更新日が4年以上前のものです。

  • 問題で使われているデータファイルはGitHubにあります。クローンは以下のようにお願いします。
$ git clone https://github.com/ryuichiueda/ShellGeiData.git
  • 環境: 解答例はUbuntu Linux 20.04で作成。Macの場合はcoreutilsをインストールすると、GNUのコマンドが使えます。BSD系の人は玄人なので各自対応のこと。

Q1

次のようなシェルスクリプトを作ります。

$ cat lineno
   echo $LINENO

このシェルスクリプトは普通に実行すると、「linenoの1行目」という意味で1が出力されます。

$ ./lineno 
   1
   $ bash lineno 
   1

このlinenoに書いたコマンドを実行して、現在操作しているBashの行番号を出力してみてください。できるひとは外部コマンドなしで実現してみましょう。

$ echo $LINENO
   58
   $ こたえ
   59

解答例

$ echo $LINENO
   58
   $ eval $(<lineno)
   59

Q2

次のように打つと、BASHで始まる変数名が列挙できます。

$ echo ${!BASH*}
   BASH BASHOPTS BASHPID BASH_ALIASES BASH_ARGC BASH_ARGV BASH_ARGV0 BASH_CMDS BASH_COMMAND BASH_COMPLETION_VERSINFO BASH_LINENO BASH_REMATCH BASH_SOURCE BASH_SUBSHELL BASH_VERSINFO BASH_VERSION

この中で、BASH_VERSIONの値が見たいと思いました。echo ${!BASH*}の前後や間にいろいろ足して、BASH_VERSIONの値を表示してください。できれば外部コマンドの利用は避けてください。

解答例

$ eval echo '$'$(a=(${!BASH*});echo ${a[-1]})
   5.0.16(1)-release
   $ eval echo '$'$(echo ${!BASH*} | sed 's/.* //')
   5.0.16(1)-release
   $ echo ${!BASH*} | awk '{print "^"$NF}' | grep -f- <(set)
   BASH_VERSION='5.0.16(1)-release'

Q3

sleepをみっつ、systemd(あるいはinitなどプロセス番号1のプロセス)の下にぶら下げてください。できるひとは100個ぶらさげてください。

解答例

$ ( sleep 100 | sleep 100 | sleep 100 & )
   $ pstree
   systemd─┬─ModemManager───2*[{ModemManager}]
   ・・・
           ├─3*[sleep]
           ├─snapd───11*[{snapd}]
   ・・・

補足: デスクトップ版だとsystemdの下のsystemdにぶら下がることがあります。

Q4

いま触っている端末上でecho $$して1が出るように細工してください。

解答例

$ sudo unshare --fork --pid --mount-proc bash
   # echo $$
   1
  • 出典:

Q5

3秒に一回、プロンプトに勝手にunkoと入力されて叱られるようにしてください。

$ unko
   
   コマンド 'unko' が見つかりません。もしかして:
   
     command 'nuko' from snap nuko (0.2.1)
   
   他のバージョンについては 'snap info <snapname>' を確認してください。
   
   $ unko
   
   コマンド 'unko' が見つかりません。もしかして:
   
     command 'nuko' from snap nuko (0.2.1)
   
   他のバージョンについては 'snap info <snapname>' を確認してください。
   
   $ unko
   
   コマンド 'unko' が見つかりません。もしかして:
   
     command 'nuko' from snap nuko (0.2.1)
   
   他のバージョンについては 'snap info <snapname>' を確認してください。

解答例

$ exec < <( while echo unko ; do sleep 3 ; done )

Q6

$SHLVLの数字でseqの役割を果たす一行のシェルスクリプトを書いて、1から順に出力を得てください。シェルレベルが限界を超えるのは気にしなくてもかまいません。

$ 出力例
   1
   2
   3
   4
   5
   ...
   999
   bash: 警告: シェルレベル (1000) は高すぎます。1に再設定されました
   1
   2
   ...

解答例

$ cat f
   echo $SHLVL && bash f
   $ ./f | head
   1
   2
   3
   4
   5
   6
   7
   8
   9
   10

Q7

つぎのように、sleepを3代ぶらさげてください。シェルスクリプトを使ってもかまいません。手が出ない場合は2代で十分です。

$ ps u --forest
   USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
   ueda       57701  0.0  0.0  12660  5784 pts/5    Ss   10:39   0:00 bash
   ueda       57992  0.0  0.0   9112   588 pts/5    S+   10:44   0:00  \_ sleep 100
   ueda       57993  0.0  0.0   9112   524 pts/5    S+   10:44   0:00      \_ sleep 100
   ueda       57994  0.0  0.0   9112   580 pts/5    S+   10:44   0:00          \_ sleep 100
   ・・・

解答例

次のようなシェルスクリプトが考えられます。

$ cat hoge2
   bash -c '
   sleep 100 &
   exec sleep 100
   ' &
   exec sleep 100

Q8

次のように2分木状にプロセスをぶらさげてください。forkbombには気をつけてくださいね。

$ ps --forest
       PID TTY          TIME CMD
    163971 pts/7    00:00:00 bash
    165295 pts/7    00:00:00  \_ bash
    165296 pts/7    00:00:00  |   \_ bash
    165297 pts/7    00:00:00  |       \_ bash
    165299 pts/7    00:00:00  |       |   \_ bash
    165327 pts/7    00:00:00  |       |   |   \_ bash
    165349 pts/7    00:00:00  |       |   |   |   \_ bash
    165355 pts/7    00:00:00  |       |   |   |   |   \_ bash
    165359 pts/7    00:00:00  |       |   |   |   |   |   \_ sleep
    165356 pts/7    00:00:00  |       |   |   |   |   \_ bash
    165350 pts/7    00:00:00  |       |   |   |   \_ bash
    165357 pts/7    00:00:00  |       |   |   |       \_ bash
    165358 pts/7    00:00:00  |       |   |   |       \_ bash
    165328 pts/7    00:00:00  |       |   |   \_ bash
    165329 pts/7    00:00:00  |       |   |       \_ bash
    165333 pts/7    00:00:00  |       |   |       |   \_ bash
    165334 pts/7    00:00:00  |       |   |       |   \_ bash
    165330 pts/7    00:00:00  |       |   |       \_ bash
    165347 pts/7    00:00:00  |       |   |           \_ bash
    165348 pts/7    00:00:00  |       |   |           \_ bash
    165300 pts/7    00:00:00  |       |   \_ bash
    165302 pts/7    00:00:00  |       |       \_ bash
    165310 pts/7    00:00:00  |       |       |   \_ bash
    165316 pts/7    00:00:00  |       |       |   |   \_ bash
    165320 pts/7    00:00:00  |       |       |   |   \_ bash
    165312 pts/7    00:00:00  |       |       |   \_ bash
    165315 pts/7    00:00:00  |       |       |       \_ bash
    165319 pts/7    00:00:00  |       |       |       \_ bash
    165304 pts/7    00:00:00  |       |       \_ bash
    165306 pts/7    00:00:00  |       |           \_ bash
    165331 pts/7    00:00:00  |       |           |   \_ bash
    165332 pts/7    00:00:00  |       |           |   \_ bash
    165308 pts/7    00:00:00  |       |           \_ bash
    165311 pts/7    00:00:00  |       |               \_ bash
    165314 pts/7    00:00:00  |       |               \_ bash
    165298 pts/7    00:00:00  |       \_ bash
    165301 pts/7    00:00:00  |           \_ bash
    165305 pts/7    00:00:00  |           |   \_ bash
    165321 pts/7    00:00:00  |           |   |   \_ bash
    165337 pts/7    00:00:00  |           |   |   |   \_ bash
    165338 pts/7    00:00:00  |           |   |   |   \_ bash
    165323 pts/7    00:00:00  |           |   |   \_ bash
    165335 pts/7    00:00:00  |           |   |       \_ bash
    165336 pts/7    00:00:00  |           |   |       \_ bash
    165307 pts/7    00:00:00  |           |   \_ bash
    165309 pts/7    00:00:00  |           |       \_ bash
    165322 pts/7    00:00:00  |           |       |   \_ bash
    165324 pts/7    00:00:00  |           |       |   \_ bash
    165313 pts/7    00:00:00  |           |       \_ bash
    165317 pts/7    00:00:00  |           |           \_ bash
    165318 pts/7    00:00:00  |           |           \_ bash
    165303 pts/7    00:00:00  |           \_ bash
    165325 pts/7    00:00:00  |               \_ bash
    165339 pts/7    00:00:00  |               |   \_ bash
    165351 pts/7    00:00:00  |               |   |   \_ bash
    165352 pts/7    00:00:00  |               |   |   \_ bash
    165340 pts/7    00:00:00  |               |   \_ bash
    165353 pts/7    00:00:00  |               |       \_ bash
    165354 pts/7    00:00:00  |               |       \_ bash
    165326 pts/7    00:00:00  |               \_ bash
    165341 pts/7    00:00:00  |                   \_ bash
    165345 pts/7    00:00:00  |                   |   \_ bash
    165346 pts/7    00:00:00  |                   |   \_ bash
    165342 pts/7    00:00:00  |                   \_ bash
    165343 pts/7    00:00:00  |                       \_ bash
    165344 pts/7    00:00:00  |                       \_ bash
    165386 pts/7    00:00:00  \_ ps

解答例

$ a=bash ; for i in {1..5} ; do a=$(sed 's/bash/(&|&)/g' <<< $a) ; done ; sed 'asleep 100;' <<< $a | bash &
ノート   このエントリーをはてなブックマークに追加 
 

prev:【問題のみ】jus共催 第48回引きこもりもりシェル芸勉強会 next:jus共催 第48回シェル芸勉強会リンク集

やり散らかし一覧

記事いろいろ