なんちゃってオンラインターミナル

なんちゃってオンラインターミナル

プロジェクトによってはFTP接続しかできないといった環境にたまに参画することもあります。
修正の影響範囲調査、バージョン情報などちょっとしたこともファイルのダウンロードやサーバの管理をしている会社への問い合わせなど時間の無駄を排除すべく最低限のことができるオンラインターミナルのサンプルコードを記載します。

```php:webconsole.php
<?php
$command = "";
$commandResult = "";
if (isset($_POST['command']) && $_POST['command'] != "") {
    $command = $_POST['command'];
    $result = shell_exec($command);
    if ($result != null) {
        $commandResult = $result;
    } else {
        $commandResult = "実行結果はありません。。。";
    }
}
$html = <<< EOM
<!doctype html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>オンラインたーみなる</title>
<script>
</script>
</head>
<body>
<header>
<h1>オンラインたーみなる</h1>
</header>
<div>
<form action="webconsole.php" method="post">
<input type="text" id="command" name="command" required size="10" value="{$command}" placeholder="コマンドを入力してください。">
<button type="submit" value="ボタン">ボタンの内容</button>
</form>
<div>
<pre>{$commandResult}</pre>
</div>
</div>
<footer>
<address>Copyright(C) Dsuke,Allright Reserved.</address>
</footer>
</body>
</html>
EOM;

echo $html;
```

このソースだけでも事足りますが多少はデザインはしておきたいところです。
<img width="342" alt="00.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171126/81b0f14f-a7d1-5d79-fd44-7c32ec9960eb.jpeg">　　
　　　　　　　　　　↓
<img width="342" alt="01.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171126/abd71336-7c06-8d2c-4105-30f820e52995.jpeg">


少しやる気を出してデザインした結果が以下です。

```php:webconsole.php
<?php
$command = "";
$commandResult = "";
if (isset($_POST['command']) && $_POST['command'] != "") {
    $command = $_POST['command'];
    $result = shell_exec($command);
    if ($result != null) {
        $commandResult = $result;
    } else {
        $commandResult = "実行結果はありません。。。";
    }
    $commandResult = "<div class='box'><pre>{$commandResult}</pre></div>";
}
$html = <<< EOM
<!doctype html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>オンラインたーみなる</title>
<style type="text/css">
<!--
#header {
    position:relative;
    margin:0 10px;
    padding:10px 10px 10px 30px;
    font:bold 22px/1.2 Arial, Helvetica, sans-serif;
    color:#666;
    text-align: center;
    background:#ccc;
    border-top:#ccc solid 1px;
    border-right:#999 solid 1px;
    border-bottom:#999 solid 1px;
    border-left:#ccc solid 1px;
    text-shadow:1px 1px 0 rgba(255,255,255,1);
    box-shadow:
        0 0 0 1px rgba(255,255,255,0.5) inset;
    background-image: -webkit-gradient(linear, left top, left bottom,
            from(             rgba(220, 220, 220, 1.0)), 
            color-stop(0.25, rgba(240, 240, 240, 1.0)),
            color-stop(0.30, rgba(235, 235, 235, 1.0)),
            color-stop(0.36, rgba(240, 240, 240, 1.0)),
            color-stop(0.50, rgba(235, 235, 235, 1.0)),
            color-stop(0.80, rgba(215, 215, 215, 1.0)),
            to(                 rgba(210, 210, 210, 1.0))
            );
    background-image: -webkit-linear-gradient(top,
            rgba(220, 220, 220, 1.0), 
            rgba(240, 240, 240, 1.0) 25%,
            rgba(235, 235, 235, 1.0) 30%,
            rgba(240, 240, 240, 1.0) 36%,
            rgba(235, 235, 235, 1.0) 50%,
            rgba(215, 215, 215, 1.0) 80%,
            rgba(210, 210, 210, 1.0)
            );
    background-image: -moz-linear-gradient(top,
            rgba(220, 220, 220, 1.0), 
            rgba(240, 240, 240, 1.0) 25%,
            rgba(235, 235, 235, 1.0) 30%,
            rgba(240, 240, 240, 1.0) 36%,
            rgba(235, 235, 235, 1.0) 50%,
            rgba(215, 215, 215, 1.0) 80%,
            rgba(210, 210, 210, 1.0)
            );
    background-image: -o-linear-gradient(top,
            rgba(220, 220, 220, 1.0), 
            rgba(240, 240, 240, 1.0) 25%,
            rgba(235, 235, 235, 1.0) 30%,
            rgba(240, 240, 240, 1.0) 36%,
            rgba(235, 235, 235, 1.0) 50%,
            rgba(215, 215, 215, 1.0) 80%,
            rgba(210, 210, 210, 1.0)
            );
    background-image: linear-gradient(to bottom,
            rgba(220, 220, 220, 1.0), 
            rgba(240, 240, 240, 1.0) 25%,
            rgba(235, 235, 235, 1.0) 30%,
            rgba(240, 240, 240, 1.0) 36%,
            rgba(235, 235, 235, 1.0) 50%,
            rgba(215, 215, 215, 1.0) 80%,
            rgba(210, 210, 210, 1.0)
            );
}
#header:before {
    content:" ";
    position:absolute;
    top:0;
    left:15px;
    width:0;
    height:100%;
    border-left:#ccc solid 1px;
}
#header:after {
    content:" ";
    position:absolute;
    top:0;
    left:16px;
    width:0;
    height:100%;
    border-right:#eee solid 1px;
}
.cmd_input {
    position: relative;
    width: 90%;
    margin: 40px 3%;
}
.cmd_input input[type='text'] {
    font: 15px/24px sans-serif;
    box-sizing: border-box;
    width: 100%;
    letter-spacing: 1px;
    padding-left: 1em;
    color: #ffffff;
    background-color: #000000;
}
.cmd_input input[type='text']:focus {
    outline: none;
}
.effect {
    padding: 7px 14px;
    transition: 0.4s;
    border: 1px solid #000000;
    background: transparent;
    color: #ffffff;
    background-color: #000000;
}
.effect ~ .focus_line:before,
.effect ~ .focus_line:after {
    position: absolute;
    top: -1px;
    left: 50%;
    width: 0;
    height: 2px;
    content: '';
    transition: 0.4s;
    background-color: #00ff00;
}
.effect ~ .focus_line:after {
    top: auto;
    bottom: 0;
}
.effect ~ .focus_line i:before,
.effect ~ .focus_line i:after {
    position: absolute;
    top: 50%;
    left: 0;
    width: 2px;
    height: 0;
    content: '';
    transition: 0.6s;
    background-color: #00ff00;
}
.effect ~ .focus_line i:after {
    right: 0;
    left: auto;
}
.effect:focus ~ .focus_line:before,
.effect:focus ~ .focus_line:after,
.cmd_input.ef ~ .focus_line:before,
.cmd_input.ef ~ .focus_line:after {
    left: 0;
    width: 100%;
    transition: 0.4s;
}
.effect:focus ~ .focus_line i:before,
.effect:focus ~ .focus_line i:after,
.cmd_input.ef ~ .focus_line i:before,
.cmd_input.ef ~ .focus_line i:after {
    top: -1px;
    height: 100%;
    transition: 0.6s;
}
.effect ~ label {
    position: absolute;
    z-index: -1;
    top: 10px;
    left:30px;
    width: 100%;
    transition: 0.3s;
    letter-spacing: 0.5px;
    color: #00ff00;
}
.effect:focus ~ label,
.cmd_input.ef ~ label {
    font-size: 18px;
    top: -20px;
    left: 0;
    transition: 0.3s;
    color: #000000;
}
button.button {
    font-size: 1.0em;
    font-weight: bold;
    padding: 5px 15px;
    background-color: #c0c0c0;
    color: #191970;
    border: 2px solid #000000;
}

button.button:hover {
    background-color: #000000;
    color: #00ff00;
}
.box {
    padding: 8px 19px;
    margin: 2em 0;
    color: #2c2c2f;
    background: #cde4ff;
    border-top: solid 5px #00ff00;
    border-bottom: solid 5px #00ff00;
    background-color: #000000;
}
.box pre {
    margin: 0; 
    padding: 0;
    color: #ffffff;
}
footer {
    font-size: 80%;
    width: 99%;
    text-align: center;
    padding-top: 10px;
    padding-bottom: 10px;
    background-color: #313131;
    position: absolute;
    bottom: 0;
}
footer address {
    color: #ffffff;
    letter-spacing: 5px;
    font-style: normal;
}
-->
</style>
</head>
<body>
<header>
<h1 id="header">オンラインたーみなる</h1>
</header>
<form action="webconsole.php" method="post">
<div class="cmd_input">
<input class="effect" type="text" id="command" name="command" value="{$command}" placeholder="">
<label>コマンドを入力してください。</label>
<span class="focus_line"><i></i></span>
</div>
<center><button class="button" type="submit" value="実行">実行</button></center>
</form>
{$commandResult}
<footer>
<address>Copyright(C) Dsuke,Allright Reserved.</address>
</footer>
</body>
</html>
EOM;

echo $html;
```

<img width="342" alt="02.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171126/b057b95a-8437-b3c9-e6b6-51800c98aa80.jpeg">

　　　　　　　　　　↓
<img width="342" alt="03.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171126/14fe3571-d355-a561-d81c-6ef768fed1ef.jpeg">


見れるレベルにはなったかと思います。（だれかデザインしてくれ）

####最後に
・バリデーションなど行っていないため各自実装してください
・いい感じのデザイン求む（ください）