bashのみでブラウザクラッシャー「you are an idiot」を再現してみた


# bashでyou are idiotを作ってみる
## 実行イメージ
- 背景と文字が白黒で点滅しながら、巨大文字でYou are idiotが出力されます。
- また、Ctrl-Cで終了しようとすると☺が増えます。
![tmp.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455763/48bf39e0-8712-ca5b-10e4-476a563880ad.gif)

![Screenshot from 2021-02-28 09-36-57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455763/d1afe338-5ef7-6a07-16d6-bf2826904130.png)


## 実行環境
- Ubntu 20.04LTS
- GNU bash, version 5.0.17(1)

## 使用したもの

### tputコマンド
tputコマンドを使うとターミナル標準出力の色を変えたり、カーソルを移動させたりすることができます。
これを使ってyou are idiotの白と黒に画面が点滅する部分を再現するのに使いました。


```bash

tput setab 0 #文字の色を黒に
tput setaf 7 #背景色を白に
```
|      |        |
|------|--------|
|色番号|色       |
|0     |黒      |
|1     |赤      |
|2     |緑      |
|3     |黄色    |
|4     |青      |
|5     |マゼンタ |
|6     |シアン   |
|7     |白      |

### trap

スクリプト終了時に関数を実行したり、Ctrl-Cのシグナルをキャプチャして関数を実行したりできます。
本当はターミナルを閉じた時に新しいウィンドウが立ち上がるようにしたかったのですが、それではbashで実装した意味がないような気がしたのでニコチャンマーク(☺)の数が増えるようにしました。

### figlet
You are idiot! hahahahahahahahahaha~の音声ファイルを流したかったところはありますが、sayコマンドで機械音声を流してもあんまり雰囲気がでなかったので代わりに大きな文字が表示できるようにしました。
figletはaptで簡単にインストールできます。

```bash
sudo apt install figlet
figlet YOU ARE IDIOT
__   _____  _   _      _    ____  _____   ___ ____ ___ ___ _____ 
\ \ / / _ \| | | |    / \  |  _ \| ____| |_ _|  _ \_ _/ _ \_   _|
 \ V / | | | | | |   / _ \ | |_) |  _|    | || | | | | | | || |  
  | || |_| | |_| |  / ___ \|  _ <| |___   | || |_| | | |_| || |  
  |_| \___/ \___/  /_/   \_\_| \_\_____| |___|____/___\___/ |_|  
                                                                 
```

## 完成形(音無し)

以下のスクリプトをコピペして実行すれば動きます。
Ctrl-Cをするたびに☺が3つずつ増えていきます。

![tmp.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455763/48bf39e0-8712-ca5b-10e4-476a563880ad.gif)




```bash
#!/bin/bash
##########################################################################
# Name: uareidiot.bash
#
# You are idiot animation
#
# Usage: ./uareidiot.bash
#
# Author: hahahahaha
# Date: 2021/02/27
##########################################################################
function changecolor()
{
    tput setab $1
    tput setaf $2
}

function cloneface()
{
    for ((n=0; n < $cnt; n++));
    do
        echo -n " ☺  ☺  ☺ "
    done
}

function cntplus()
{
    let cnt++
}

declare -i cnt=1
trap cntplus {1,2,3,15}

declare -i i=0 t=7 tmp

while true
do
    clear
    changecolor $i $t && cloneface #echo "☺  ☺  ☺ "
    echo -n -e "\n"
    figlet "YOU ARE IDIOT"
    sleep 1
    tmp=$i
    i=$t
    t=$tmp
done

```

## 止め方
このプログラムは実行するとCtrl-CやCtrl-\などのシグナルをキャプチャして☺が増えるようになっているため、プロセスからキルする必要があります。
今回の設定の場合は単純にkillするだけでなく、-KILLオプションを使わないと止まらないのでご注意を!(ターミナルを消してもバックグラウンドで走っています)。

```
ps -e | grep uareidiot.bash
kill -KILL <process ID>
```

## 追記 音を出したい
　やはりあのうざい音がでないと面白くないのではと思い、soxを使って音を出すことにしました。
単純に音を出すスクリプトを挿入すると、音声再生が終わるまで次の処理が行われず、点滅が止まってしまう問題が発生しました。そこで、音を出す部分をバックグラウンド処理にしたところ、音がでなくなってしまいましたがsoxの-qオプションをつけることでバックグラウンド処理でも音が出るようになりました。
また、今回は音が被ってしまうのを避けるためにplayのプロセスが存在する間は音声がならないように設定しました。
　音源に関しては、youtubeに転がっているものをダウンロードして、ffmpegでいらない部分をカットして使いました。音源は./music/youareidiot.mp3に保存しています。

### soxのインストール

```
sudo apt install sox
sudo apt install libsox-fmt-mp3 #soxのmp3用のパッケージを追加
play test.mp3
```

### 音源が再生されていない時のみ音源を再生する(重ねて再生しない)

```bash

if ps -e | grep play > /dev/null 2>&1; then
    :
else
    play -q ./music/youareidiot.mp3 > /dev/null 2>&1 & #-qオプションでバックグラウンドで実行しても音が出る。
```

## 完成形(音あり)
音を出すところ以外に大きな変更点はないですが一応掲載します。

```bash

#!/bin/bash
##########################################################################
# Name: uareidiot.bash
#
# You are idiot animation
#
# Usage: ./uareidiot.bash
#
# Author: hahahahaha
# Date: 2021/02/27
##########################################################################
unction changecolor()
{
    tput setab $1
    tput setaf $2
}

function cloneface()
{
    for ((n=0; n < $cnt; n++));
    do
        echo -n " ☺  ☺  ☺ "
    done
}

function cntplus()
{
    let cnt++ #number of press Ctrl-C
}

declare -i cnt=1
trap cntplus {1,2,3,15}

declare -i i=0 t=7 tmp

while true
do
    clear
    figlet "YOU ARE IDIOT"
    changecolor $i $t && cloneface
    echo -n -e "\n"
    if ps -e | grep play > /dev/null 2>&1; then
        :
    else
        play -q ./music/youareidiot.mp3 > /dev/null 2>&1 &
    fi
    sleep 1
    tmp=$i
    i=$t
    t=$tmp
done
```


## 終わりに
ご意見や、改善点などお待ちしております。楽しんでいただければ幸いです。
(自分としては面白いと思って作ったのに反応が薄い気がして悲しいです。ネタが古すぎたのか...)