mk-toolブログ

エンジニアと家のことをごちゃごちゃと書いてます

【Docker】docker-composeでExited (0)とかでるとき

概要

docker-composeでExited (0)が出て全然コンテナが立ち上がらないので困り果てたのでメモ。

本文

dockerコンテナの立ち上げ結果をみた際にExited (0)が出るので対策を調べてみたら、dockerのimageから起動してみる記事にありついた。 以下のコマンドでimageからdockerコンテナを起動することができる。

docker run -d -t -i [イメージ名] /bin/bash

これを実行してみると、imageからの起動は問題なかった。 ということはdocker-compose側での問題なんだろうな、という問題の切り分けができた。 なので「docker-compose Exited (0)」で調べたらstackoverflowがヒットした。

docker-compose.yml中のコンテナの設定にtty: trueを記載すれば良いとのことだったので追記したところうまく動いた。ちなみに、ttyは上記のdockerコマンドの-tと同一の指定とのこと。

【Python】The session is unavailable because no secret key was set.

概要

以下のエラーが発生したため対処。

The session is unavailable because no secret key was set.

本題

Flaskでsession変数を扱う際は、以下のようにする。

from flask import session

// 略

session['user_id'] = "hogehoge"

しかしながら、secret keyを設定していないとエラーが発生する。 そのためsession変数を扱うより前の場所でsecret keyを設定する。

if __name__ == "__main__":
    app.secret_key = 'secret key'

これで解決

参考

stackoverflow.com

【Go】逆ポーランドを出力

概要

いまさらですが逆ポーランドを出力するものを書く。 元ネタは改訂第4版 C言語によるはじめてのアルゴリズム入門

本題

逆ポーランドを出力するためには、数値と演算子の優先度を比較しながらstackに値を一時格納する。 逆ポーランドの出力が確定した部分からpolishへ格納していく。

豆知識として、Goは*p++のようなポインタの演算ができないことを知った。また、polish[sp2++]のようにindexでインクリメントを利用することは、インクリメントがコンパイラに式ではなく文として解釈されるためできないことも知った。

以下ソースコード

package main

import (
    "fmt"
)

var stack [10]string
var polish [10]string

func main() {
    formula := "a+b-c*d/e"
    sp1, sp2 := 0, 0

    // 優先順位テーブル
    pri := map[string]int{
        "a": 3, "b": 3, "c": 3, "d": 3, "e": 3,
        "+": 1, "-": 1, "*": 2, "/": 2, "": -1,
    }

    for _, v := range formula {
        for pri[string([]rune{v})] <= pri[stack[sp1]]{
            popAndPush(&sp1, &sp2)
        }
        sp1++
        stack[sp1] = string([]rune{v})
    }
        // stackにたまっているものをpolishへ
    for sp1 > 0{
        popAndPush(&sp1, &sp2)
    }
    fmt.Println(polish)
}

func popAndPush(sp1 *int, sp2 *int){
    *sp2++
    polish[*sp2] = stack[*sp1]
    *sp1--
}

出力結果

[ a b + c d * e / -]

参考

Goのポインタの使いかた

1文字ずつアクセスする

mapの作り方(今回使っていないけど)

mapについて(今回使っていないけど)

【Go】順リストを書く

概要

いまさらですが順リストを書く。 元ネタは改訂第4版 C言語によるはじめてのアルゴリズム入門

本題

以下ソースコードold.pointer = nの次にold = nとあるのですが、これってoldの指すアドレスを変えるってことなんだな、と理解するまでに苦労した。オブジェクトとして考えてはいけない。

package main

import (
    "fmt"
)

type node struct {
    name string
    tel string
  pointer *node
}

func main() {
    var head *node = new(node)
    var old *node = head

    for{
        n := new(node)
        fmt.Println("name tel")
        fmt.Scanf("%s %s", &n.name, &n.tel)
        old.pointer = n
        old = n

        if(!next()){
            show(head.pointer)
            break
        }
    }
}

func show(n *node) {
    fmt.Println("/////順リスト/////")
    for{
        if(n == nil){
            break
        }
        fmt.Printf("%s %s", n.name, n.tel)
        fmt.Println("")
        n = n.pointer
    }
}

func next() bool {
    continue_str := ""
    for{
        fmt.Println("continue? [y/n]")
        fmt.Scanf("%s", &continue_str)
        if(continue_str == "y"){
            return true
        }
        if(continue_str == "n"){
            return false
        }
    }
}

結果 name telと聞かれるので適当な文字列を半角スペース区切りで2つ入力する。 continueの旨を聞かれるのでy/nで回答。 yをすると、もう一度name telと聞かれる繰り返し。 nをすると作られたリストが表示される。

name tel
a 1
continue? [y/n]
y
name tel
b 2
continue? [y/n]
y
name tel
c 3
continue? [y/n]
n
/////順リスト/////
a 1
b 2
c 3

【Go】逆順リストを書く

概要

いまさらですが逆順リストを書く。 元ネタは改訂第4版 C言語によるはじめてのアルゴリズム入門

本題

以下ソースコード

package main

import (
    "fmt"
)

type node struct {
    name string
    tel string
  pointer *node
}

func main() {
    var head *node = nil

    for{        
        n := new(node)
        fmt.Println("name tel")
        fmt.Scanf("%s %s", &n.name, &n.tel)
        n.pointer = head
        head = n

        if(!next()){
            show(n)
            break
        }
    }
}

func show(n *node) {
    fmt.Println("/////逆順リスト/////")
    for{
        if(n == nil){
            break
        }
        fmt.Printf("%s %s", n.name, n.tel)
        fmt.Println("")
        n = n.pointer
    }
}

func next() bool {
    continue_str := ""
    for{
        fmt.Println("continue? [y/n]")
        fmt.Scanf("%s", &continue_str)
        if(continue_str == "y"){
            return true
        }
        if(continue_str == "n"){
            return false
        }
    }
}

結果 name telと聞かれるので適当な文字列を半角スペース区切りで2つ入力する。 continueの旨を聞かれるのでy/nで回答。 yをすると、もう一度name telと聞かれる繰り返し。 nをすると作られたリストが表示される。

name tel
aaa 000
continue? [y/n]
b
continue? [y/n]
y
name tel
bbb 111
continue? [y/n]
n
/////逆順リスト/////
bbb 111
aaa 000

【Go】キューを書く

概要

いまさらですがキューを書きます。 元ネタは改訂第4版 C言語によるはじめてのアルゴリズム入門です。

本題

以下ソースコード

package main

import (
    "fmt"
)

const MAXSIZE = 5 // キューの最大長
var queue [5]int
var head int = 0 // キューの先頭
var tail int = 0 // キューの最後尾

func main() {
    var n int = 0
    for {
        fmt.Print("queuein(i) or queueout(o)?")
        var operator string
        fmt.Scanf("%s", &operator)

        if(operator == "queuein" || operator == "i"){
            fmt.Print("number: ")
                fmt.Scanf("%d", &n)
            if(queuein(n) == -1){
                fmt.Println("キューがいっぱいです")
            }
        }
        if(operator == "queueout" || operator == "o"){
            if(queueout(&n) == -1){
                fmt.Println("キューは空です")
            }
        }
        show()
    }
}

func queuein(n int) int {
    if(head != (tail + 1) % MAXSIZE){
        queue[tail] = n
        tail = (tail + 1) % MAXSIZE
        return 0
    }
    return -1
}

func queueout(n *int) int {
    if(head != tail){
        *n = queue[head]
        fmt.Println("out: ", *n)
        head = (head + 1) % MAXSIZE
        return 0
    }else{
        return -1
    }
}

func show() {
    fmt.Println("/////current queue/////")
    for i, v := range queue {
        if(i == head){
            fmt.Print("*")
        }
        if(i == tail){
            fmt.Print("~")
        }
        fmt.Printf("%d ", v)
    }
    fmt.Println("")
    fmt.Println("")
}

結果 *がついた部分はキューの先頭で、~がついた部分はキューの末尾。 queuein(i) or queueout(o)? と質問されるので、 queueinかiを入力すればキューに入れ、queueoutかiを入力すればキューから取り出すことができる。 queueinの場合はキューに入れる数値の入力を求められる。 queueoutの場合はキューから取り出した値を表示する。

queuein(i) or queueout(o)?i
number: 1
/////current queue/////
*1 ~0 0 0 0

queuein(i) or queueout(o)?i
number: 2
/////current queue/////
*1 2 ~0 0 0

queuein(i) or queueout(o)?i
number: 3
/////current queue/////
*1 2 3 ~0 0

queuein(i) or queueout(o)?i
number: 4
/////current queue/////
*1 2 3 4 ~0

queuein(i) or queueout(o)?i
number: 5
キューがいっぱいです
/////current queue/////
*1 2 3 4 ~0

queuein(i) or queueout(o)?o
out:  1
/////current queue/////
1 *2 3 4 ~0

queuein(i) or queueout(o)?o
out:  2
/////current queue/////
1 2 *3 4 ~0

queuein(i) or queueout(o)?o
out:  3
/////current queue/////
1 2 3 *4 ~0

queuein(i) or queueout(o)?o
out:  4
/////current queue/////
1 2 3 4 *~0

queuein(i) or queueout(o)?o
キューは空です
/////current queue/////
1 2 3 4 *~0

【Go】スタックを書く

概要

いまさらですがスタックを書きます。 元ネタは改訂第4版 C言語によるはじめてのアルゴリズム入門です。

本題

以下ソースコード

package main

import (
    "fmt"
)

const MAXSIZE = 5 // スタックの最大長
var stack [5]int
var sp int = 0 // スタックポインタ

func main() {
    var n int = 0
    for {
        fmt.Print("push(o) or pop(i)?")
        var operator string
        fmt.Scanf("%s", &operator)

        if(operator == "push" || operator == "o"){
            fmt.Print("number: ")
                fmt.Scanf("%d", &n)
            if(push(n) == -1){
                fmt.Println("スタックがいっぱいです")
            }
        }
        if(operator == "pop" || operator == "i"){
            if(pop(&n) == -1){
                fmt.Println("スタックは空です")
            }
        }
        show()
    }
}

func push(n int) int {
    if(sp < MAXSIZE){
        stack[sp] = n
        sp++
        return 0
    }
    return -1
}

func pop(n *int) int {
    if(sp > 0){
        sp--
        *n = stack[sp]
        fmt.Println("poped: ", *n)
        return 0
    }else{
        return -1
    }
}

func show() {
    fmt.Println("/////current stack/////")
    for i, v := range stack {
        if(i == (sp - 1)){
            fmt.Printf("*")         
        }
        fmt.Printf("%d ", v)
    }
    fmt.Println("")
    fmt.Println("")
}

使い方 push(o) or pop(i)?でpushしたい場合はpushoを入力、popしたい場合はpopiを入力。 pushの場合はnumberが聞かれるので数値を入力する。 そうすると、現在のスタックの状態が表示される。 なお*が付いている部分は現在のスタックポインタの位置。 popした際は、どの値がpopされたかを表示する。

出力結果

push(o) or pop(i)?o
number: 1
/////current stack/////
*1 0 0 0 0

push(o) or pop(i)?o
number: 2
/////current stack/////
1 *2 0 0 0

push(o) or pop(i)?o
number: 3
/////current stack/////
1 2 *3 0 0

push(o) or pop(i)?o
number: 4
/////current stack/////
1 2 3 *4 0

push(o) or pop(i)?o
number: 5
/////current stack/////
1 2 3 4 *5

push(o) or pop(i)?o
number: 6
スタックがいっぱいです
/////current stack/////
1 2 3 4 *5

push(o) or pop(i)?i
poped:  5
/////current stack/////
1 2 3 *4 5

push(o) or pop(i)?i
poped:  4
/////current stack/////
1 2 *3 4 5

push(o) or pop(i)?i
poped:  3
/////current stack/////
1 *2 3 4 5

push(o) or pop(i)?i
poped:  2
/////current stack/////
*1 2 3 4 5

push(o) or pop(i)?i
poped:  1
/////current stack/////
1 2 3 4 5

push(o) or pop(i)?i
スタックは空です
/////current stack/////
1 2 3 4 5