2016年5月31日 星期二

[ 常見問題 ] How can I set a static IP address in a Docker container?

Source From Here 
Question 
I'm perfectly happy with the IP range that docker is giving me by default (176.17.x.x), so I don't need to create a new bridge, I just want to give my containers a static address within that range so I can point client browsers to it directly. 

How-To 
I used the method written here in the official Docker documentation and I confirm it's working: 
# docker images
# d run -it --rm --net=none johnklee/hadoop_centos_base:v1 /bin/bash // Run container on image johnklee/hadoop_centos_base:v1

// At another shell, learn the container process ID
// and create its namespace entry in /var/run/netns/
// for the "ip netns" command we will be using below

# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6f072051949b johnklee/hadoop_centos_base:v1 "/bin/bash" About a minute ago Up About a minute prickly_lumiere
 // Container ID = 6f072051949b
# d inspect -f '{{.State.Pid}}' 6f072051949b
73172
# mkdir -p /var/run/netns
# ln -sf /proc/73172/ns/net /var/run/netns/73172

// Check the bridge's IP address and netmask
# ip addr show docker0
3: docker0: mtu 1500 qdisc noqueue state DOWN
link/ether 02:42:ff:5d:2b:07 brd ff:ff:ff:ff:ff:ff
inet 172.17.42.1/16 scope global docker0
...


// Create a pair of "peer" interfaces A and B,
// bind the A end to the bridge, and bring it up

# ip link add A type veth peer name B
# brctl addif docker0 A
# ip link set A up

// Place B inside the container's network namespace,
// rename to eth0, and activate it with a free IP

# ip link set B netns 73172
# ip netns exec 73172 ip link set dev B name eth0
# ip netns exec 73172 ip link set eth0 up
# ip netns exec 73172 ip addr add 172.17.42.100/16 dev eth0
# ip netns exec 73172 ip route add default via 172.17.42.1

// Back to docker container terminal to confirm the setting is working
[root@6f072051949b /]# ip addr show
...
134: eth0: mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 16:83:8b:a3:49:58 brd ff:ff:ff:ff:ff:ff
inet 172.17.42.100/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::1483:8bff:fea3:4958/64 scope link
valid_lft forever preferred_lft forever

[root@6f072051949b /]# ping -c 3 www.google.com.tw
PING www.google.com.tw (74.125.203.94) 56(84) bytes of data.
64 bytes from th-in-f94.1e100.net (74.125.203.94): icmp_seq=1 ttl=127 time=123 ms
64 bytes from th-in-f94.1e100.net (74.125.203.94): icmp_seq=2 ttl=127 time=89.0 ms
...
 


Supplement 
[ 常見問題 ] Add link between container and bridge

2016年5月30日 星期一

[Linux 常見問題] Bash: How to read one line at a time from output of a command?

Source From Here
Question
I am trying to read the output of a command in bash using a while loop:
- test.sh
  1. #!/bin/bash  
  2. while read -r line  
  3. do  
  4.     echo "$line"  
  5. done <<< $(find . -type f)  
The output I got:
# ./test.sh
./DebugPy.py ./DebugPy.pyc ./zombe.py ./test.sh

After this I tried:
- test2.sh
  1. #!/bin/bash  
  2. $(find . -type f) |  
  3. while read -r line  
  4. do  
  5.     echo "$line"  
  6. done  
but it generated an error "Error: Must provide process id to debug" So, how do I read it line by line because I think currently it is slurping the entire line at once.

How-To
There's a mistake, you need < <(command) not <<<$(command)< <( ) is a Process Substitution$() is a command substitution and <<< is a here-string. So you can do it this way:
- test3.sh
  1. #!/bin/bash  
  2. find . -type f |  
  3. while read -r line; do  
  4.   echo "$line"  
  5. done  
The execution result:
# ./test3.sh
./DebugPy.py
./DebugPy.pyc
./test3.sh
./test2.sh
./zombe.py
./test.sh
Another approach using Process Substitution:
- test4.sh
  1. #!/bin/bash  
  2. while read -r line; do  
  3.     echo "$line"  
  4. done < <(find . -type f)  
Some advantages of process substitution:
* No need to save temporary files.
* Better performance. Reading from another process often faster than writing to disk, then read back in.
* Save time to computation since when it is performed simultaneously with parameter and variable expansion, command substitution, and arithmetic expansion


[ 英語發燒句 ] Part-51


274. "不用捶胸頓足"
A. I can't believe how terrible my presentation to the class turned out to be.
B. Stop kicking yourself. It's not the end of the world.


275. "別搞砸了"
A. I need to buy the plane tickets for our vacation soon.
B. Don't drop the ball on this one. It is high season, and the cheap tickets will sell out fast.


276. "他被當成耳邊風"
A. Did you tell your husband that it would be a risky bet to invest in that company?
B. I did, but it fell on deaf ears. The stocks we own are now almost worthless.


277. "別拿我出氣"
A. Mom yelled at me for not cleaning the kitchen. You used the kitchen too, but she said nothing to you.
B. Don't take it out on me. I didn't make a mess like you did.

Note. 類似說法: vent sth on sb

278. "非常時期需要非常手段"
A. I heard that Matt is selling his car.
B. Yeah, he just lost his job. Drastic times call for drastic measures.


279. "大做文章"
A. Did you hear about the latest scandal that politician is involved in?
B. Of course! The press is having a field day with it.

Note. field day 表示 "重要活動的日子; 大好時機; 令人相當愉快的時間", have a field day 可用來指某人可以盡情, 肆意地做事, 而所做的事可能會傷害其他人.

2016年5月25日 星期三

[ Python 常見問題 ] Is it possible to attach a console into a running process

Source From Here
Question
I just want to see the state of the process, is it possible to attach a console into the process, so I can invoke functions inside the process and see some of the global variables.

How-To
If you have access to the program's source-code, you can add this functionality relatively easily. See Recipe 576515: Debugging a running python process by interrupting and providing an interactive prompt (Python):
This provides code to allow any python program which uses it to be interrupted at the current point, and communicated with via a normal python interactive console. This allows the locals, globals and associated program state to be investigated, as well as calling arbitrary functions and classes. To use, a process should import the module, and call listen() at any point during startup. To interrupt this process, the script can be run directly, giving the process Id of the process to debug as the parameter.

A simple user case can be referred as below. Firstly, our fake main program zombe.py:
- zombe.py
  1. #!/usr/bin/env python  
  2. import time  
  3. import DebugPy  
  4. import pdb  
  5. import sys  
  6.   
  7. cnt=0  
  8. DebugPy.listen()  # This is key point for the main program being able to be intercepted by Linux signal  
  9.   
  10.   
  11. def test():  
  12.     print("This is testing function in zombe")  
  13.   
  14. while True:  
  15.     cnt = cnt + 1  
  16.     print("Count %d...(sleep 10 min)" % (cnt))  
  17.     time.sleep(1*60)  
Which will use while loop to keep running as zombie. Then is the module which will help us intercept the running Python process for debugging:
- DebugPy.py
  1. #!/usr/bin/env python  
  2. tryimport readline  # For readline input support  
  3. except: pass  
  4.   
  5. import sys, os, traceback, signal, codeop, cStringIO, cPickle, tempfile  
  6.   
  7. def pipename(pid):  
  8.     """Return name of pipe to use"""  
  9.     return os.path.join(tempfile.gettempdir(), 'debug-%d' % pid)  
  10.   
  11. class NamedPipe(object):  
  12.     def __init__(self, name, end=0, mode=0666):  
  13.         """Open a pair of pipes, name.in and name.out for communication  
  14.         with another process.  One process should pass 1 for end, and the  
  15.         other 0.  Data is marshalled with pickle."""  
  16.         self.in_name, self.out_name = name +'.in',  name +'.out',  
  17.         try: os.mkfifo(self.in_name,mode)  
  18.         except OSError: pass  
  19.         try: os.mkfifo(self.out_name,mode)  
  20.         except OSError: pass  
  21.   
  22.         # NOTE: The order the ends are opened in is important - both ends  
  23.         # of pipe 1 must be opened before the second pipe can be opened.  
  24.         if end:  
  25.             self.inp = open(self.out_name,'r')  
  26.             self.out = open(self.in_name,'w')  
  27.         else:  
  28.             self.out = open(self.out_name,'w')  
  29.             self.inp = open(self.in_name,'r')  
  30.         self._open = True  
  31.   
  32.     def is_open(self):  
  33.         return not (self.inp.closed or self.out.closed)  
  34.   
  35.     def put(self,msg):  
  36.         if self.is_open():  
  37.             data = cPickle.dumps(msg,1)  
  38.             self.out.write("%d\n" % len(data))  
  39.             self.out.write(data)  
  40.             self.out.flush()  
  41.         else:  
  42.             raise Exception("Pipe closed")  
  43.   
  44.     def get(self):  
  45.         txt=self.inp.readline()  
  46.         if not txt:  
  47.             self.inp.close()  
  48.         else:  
  49.             l = int(txt)  
  50.             data=self.inp.read(l)  
  51.             if len(data) < l: self.inp.close()  
  52.             return cPickle.loads(data)  # Convert back to python object.  
  53.   
  54.     def close(self):  
  55.         self.inp.close()  
  56.         self.out.close()  
  57.         try: os.remove(self.in_name)  
  58.         except OSError: pass  
  59.         try: os.remove(self.out_name)  
  60.         except OSError: pass  
  61.   
  62.     def __del__(self):  
  63.         self.close()  
  64.   
  65. def remote_debug(sig,frame):  
  66.     """Handler to allow process to be remotely debugged."""  
  67.     def _raiseEx(ex):  
  68.         """Raise specified exception in the remote process"""  
  69.         _raiseEx.ex = ex  
  70.     _raiseEx.ex = None  
  71.   
  72.     try:  
  73.         # Provide some useful functions.  
  74.         locs = {'_raiseEx' : _raiseEx}  
  75.         locs.update(frame.f_locals)  # Unless shadowed.  
  76.         globs = frame.f_globals  
  77.   
  78.         pid = os.getpid()  # Use pipe name based on pid  
  79.         pipe = NamedPipe(pipename(pid))  
  80.   
  81.         old_stdout, old_stderr = sys.stdout, sys.stderr  
  82.         txt = ''  
  83.         pipe.put("Interrupting process at following point:\n" +  
  84.                ''.join(traceback.format_stack(frame)) + ">>> ")  
  85.   
  86.         try:  
  87.             while pipe.is_open() and _raiseEx.ex is None:  
  88.                 line = pipe.get()  
  89.                 if line is None: continue # EOF  
  90.                 txt += line  
  91.                 try:  
  92.                     code = codeop.compile_command(txt)  
  93.                     if code:  
  94.                         sys.stdout = cStringIO.StringIO()  
  95.                         sys.stderr = sys.stdout  
  96.                         exec code in globs,locs  
  97.                         txt = ''  
  98.                         pipe.put(sys.stdout.getvalue() + '>>> ')  
  99.                     else:  
  100.                         pipe.put('... ')  
  101.                 except:  
  102.                     txt='' # May be syntax err.  
  103.                     sys.stdout = cStringIO.StringIO()  
  104.                     sys.stderr = sys.stdout  
  105.                     traceback.print_exc()  
  106.                     pipe.put(sys.stdout.getvalue() + '>>> ')  
  107.         finally:  
  108.             sys.stdout = old_stdout # Restore redirected output.  
  109.             sys.stderr = old_stderr  
  110.             pipe.close()  
  111.   
  112.     except Exception:  # Don't allow debug exceptions to propogate to real program.  
  113.         traceback.print_exc()  
  114.   
  115.     if _raiseEx.ex is not None: raise _raiseEx.ex  
  116.   
  117. def debug_process(pid):  
  118.     """Interrupt a running process and debug it."""  
  119.     os.kill(pid, signal.SIGUSR1)  # Signal process.  
  120.     pipe = NamedPipe(pipename(pid), 1)  
  121.     try:  
  122.         while pipe.is_open():  
  123.             txt=raw_input(pipe.get()) + '\n'  
  124.             pipe.put(txt)  
  125.     except EOFError:  
  126.         pass # Exit.  
  127.     pipe.close()  
  128.   
  129. def listen():  
  130.     signal.signal(signal.SIGUSR1, remote_debug) # Register for remote debugging.  
  131.   
  132. if __name__=='__main__':  
  133.     if len(sys.argv) != 2:  
  134.         print "Error: Must provide process id to debug"  
  135.     else:  
  136.         pid = int(sys.argv[1])  
  137.         debug_process(pid)  
Then you can use it this way:
# ./zombe.py & // Launch zombe in background
[1] 22266
# ./DebugPy.py 22266 // Attach into zombe process with PID
Interrupting process at following point:
File "./zombe.py", line 21, in
time.sleep(1*60)

>>> cnt // Check the variable cnt in zombe process
1
>>> test() // Call the function available in zombe process
This is testing function in zombe

Another implementation of roughly the same concept is provided by rconsole. From the documentation:
rconsole is a remote Python console with auto completion, which can be used to inspect and modify the namespace of a running script. To invoke in a script do:
  1. from rfoo.utils import rconsole  
  2. rconsole.spawn_server()  
To attach from a shell do:
$ rconsole

Security note: The rconsole listener started with spawn_server() will accept any local connection and may therefore be insecure to use in shared hosting or similar environments!


[ Python 常見問題 ] How to shift a datetime object by 12 hours in python

Source From   Here   Question   Datetime   objects hurt my head for some reason. I am writing to figure out   how to shift a date time obje...