メモ：「なるほどUnixプロセス」のサンプルコードをPythonに

# 概要
「なるほどUnixプロセス」の本文中のコードはRubyで書かれているが、Pythonを勉強中のため書き直した。全てではない。

# 環境
 * Ubuntu 17.10
 * Python 3.6

# 3章、４章
実行中のインタープリタのプロセスID、親プロセスのPID

```
>>> import os
>>> os.getpid()
2193
>>> os.getppid()
1837
```

# 5章

ファイルディスクリプタ番号

```
>>> passwd = open('/etc/passwd')
>>> passwd.fileno()
3

>>> hosts = open('/etc/hosts')
>>> hosts.fileno()
4

>>> passwd.close()

>>> null = open('/dev/null')
>>> null.fileno()
3

```

閉じたファイルディスクリプタ番号を読もうとすると？

```
>>> passwd = open('/etc/passwd')
>>> passwd.fileno()
5
>>> passwd.close()
>>> passwd.fileno()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: I/O operation on closed file
```

標準入力、標準出力、標準エラー出力のファイルディスクリプタ番号を確認する。

```
>>> import sys
>>> sys.stdin.fileno()
0
>>> sys.stdout.fileno()
1
>>> sys.stderr.fileno()
2
```

# 6章

現在のプロセスが開けるファイル記述子の上限（ソフトリミット、ハードリミット）
https://docs.python.jp/3/library/resource.html

```
>>> import resource
>>> resource.getrlimit(resource.RLIMIT_NOFILE)
(1024, 4096)

```

ソフトリミットを変更。そして上限を超えてみる。

```
>>> resource.setrlimit(resource.RLIMIT_NOFILE, (3, 4096))
>>> passwd = open('/dev/null')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 24] Too many open files: '/dev/null'
```

# 7章

環境変数を設定して参照。

```
aki@aki-MS-7823:~$ MESSAGE='wing it' python3 -c "import os; print(os.getenv('MESSAGE'))"
wing it
```

# 8章

引数を表示。

```
$ cat argv.py 
import sys

print(sys.argv[1:])

$ python3 argv.py  foo bar -va
['foo', 'bar', '-va']
```

# 9章

プロセス名を操る。

```
# 標準モジュールでは無理っぽい
sudo pip3 install setproctitle
```

```
$ python3
>>> import setproctitle
>>> setproctitle.getproctitle()
'python3'
>>> setproctitle.setproctitle('Process 1')
>>> setproctitle.getproctitle()
'Process 1'
```

# 10章

プロセスを終了する。

```
import sys

sys.exit(1)
```

例外の送出。

```
$ cat foo.py 
raise Exception('a')

$ python foo.py 
Traceback (most recent call last):
  File "foo.py", line 1, in <module>
    raise Exception('a')
Exception: a

$ echo $?
1
```


# 11章

```
$ cat fork.py 
import os

if os.fork():
    print("entered the if block")
else:
    print("entered the else block")

$ python fork.py 
entered the if block
entered the else block
```

# 12章

孤児プロセス

```
import os
import time
import sys

if not os.fork():
    for i in range(5):
        time.sleep(1)
        print("I'm an orphan!")

sys.exit(1)
```

# 14章
子プロセスの終了を待つ。

```
import os
import time
import sys

if not os.fork():
    for i in range(5):
        time.sleep(1)
        print("I'm an orphan!")

try:
    os.wait()
except ChildProcessError:
    pass

sys.exit(1)
```

終了した子プロセスのPIDを取得する方法はわからなかった。


# 16章

sleepし続ける。

```
import os
import sys
import time

print(os.getpid())

while True:
    time.sleep(10)
```

シグナルを送る。

```
>>> import os
>>> import signal
>>> os.kill(12436, signal.SIGINT)
>>> Traceback (most recent call last):
  File "sleep.py", line 8, in <module>
    time.sleep(10)
KeyboardInterrupt

>>> 
[1]+  終了 1                python sleep.py
```


シグナルをトラップする。

```
import signal, os
import time

def handler(signum, frame):
    print("Na na na, you can't get me")


signal.signal(signal.SIGINT, handler)

while True:
    time.sleep(10)

```

# 17章

パイプを使う。

```
>>> import pipes
>>> t = pipes.Template()
>>> f = t.open('pipefile', 'w')
>>> f.write('hello')
5
>>> f.close()
>>> open('pipefile').read()
'hello'
```

# 参考文献
 * なるほどUnixプロセス ― Rubyで学ぶUnixの基礎
    * https://tatsu-zine.com/books/naruhounix