Categories
Books Life productivity

그대는 원하지도 않는 수많은 일을 계속한다

그대는 원하지도 않는 수많은 일을 계속한다. 누가 그대를 강요하는가? 그대는 표류하고 있다. 아무도 그대를 강요하지 않는다. 그대는 왜 그런 일들을 하는가? 그대는 깨어 있지 못하다. 이것은 사슬과 같다. 한 가지 일을 하면 또 다른 일이 생겨난다. 하나의 일이 다른 일을 끌어오고, 이런 식으로 계속된다. 그대는 언제 멈출 것인가? 매순간이 멈추기에 알맞은 순간이다. 관찰하라. 그리고 그대 스스로 만든 이 거짓의 연결 고리에서 벗어나라.

서양의 붓다 헤라클레이토스 강론 110 페이지.

 

 

Categories
Daily

쉬어가는 페이지

London 길거리 사진 몇 장 올립니다. 🙂

# 하나

# 두울

# 세엣

# 네엣

# 집으로

사진 촬영에는 LG-E900 이 수고해주셨습니다.

끝 ^_^

Categories
Daily

Play! 프로세스 제목이 너무 길어서

Play! framework에 한가지 불만이 있다면 $ ps -ef | grep play.server 의 결과가 너무 길다는 것이다. 내 개발환경에서는 4KB가 넘는다.

$ ps -ef | grep play.server
501 35419 35418 0 9:13pm ttys001 0:01.93 /Library/Java/Home/bin/java -javaagent:/Users/rath/work/dist/play-1.2.4/framework/play-1.2.4.jar -XX:-UseSplitVerifier -Dfile.encoding=utf-8 -Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n -Dplay.debug=yes -classpath /Users/rath/work/goethe-play/conf:/Users/rath/work/dist/play-1.2.4/framework/play-1.2.4.jar:/Users/rath/work/goethe-play/lib/jakarta-regexp-1.4.jar:/Users/rath/work/goethe-play/lib/lucene-analyzers-3.5.0.jar:/Users/rath/work/goethe-play/lib/lucene-core-3.5.0.jar:/Users/rath/work/goethe-play/lib/lucene-queries-3.5.0.jar:/Users/rath/work/goethe-play/lib/rath-adrenaline-0.8.5.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/activation-1.1.1.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/antlr-2.7.6.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/asm-all-3.3.1.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/async-http-client-1.6.5.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/bcprov-jdk15-1.45.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/c3p0-0.9.1.2.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/cglib-nodep-2.2.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/commons-beanutils-1.8.3.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/commons-codec-1.4.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/commons-collections-3.2.1.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/commons-email-1.2.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/commons-fileupload-1.2.2.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/commons-io-2.0.1.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/commons-javaflow-1066591.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/commons-lang-2.6.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/commons-logging-1.1.1.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/dom4j-1.6.1.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/ehcache-core-2.0.0.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/ezmorph-1.0.3.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/geronimo-servlet_2.5_spec-1.2.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/groovy-all-1.7.10.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/gson-1.7.1.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/h2-1.3.149.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/hibernate-commons-annotations-3.2.0.Final.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/hibernate-core-3.6.1.Final.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/hibernate-entitymanager-3.6.0.Final.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/hibernate-jpa-2.0-api-1.0.0.Final.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/ivy-2.2.0.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/jamon-2.7.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/javassist-3.9.0.GA.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/javax.inject-1.0.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/jaxen-1.1.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/jj-imaging.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/jj-simplecaptcha.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/jj-textile.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/jj-wikitext.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/joda-time-2.0.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/jregex-1.2_01.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/jsr107cache-1.0.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/jta-1.1.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/junit-4.8.1.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/log4j-1.2.16.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/mail-1.4.3.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/memcached-2.6.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/mysql-connector-java-5.1.13.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/netty-3.2.5.Final.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/org.eclipse.jdt.core-3.8.0.v_C03.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/oval-1.50.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/postgresql-9.0.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/signpost-core-1.2.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/slf4j-api-1.6.1.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/slf4j-log4j12-1.6.1.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/snakeyaml-1.7.jar:/Users/rath/work/dist/play-1.2.4/framework/lib/xstream-1.3.jar -Dapplication.path=/Users/rath/work/goethe-play -Dplay.id= play.server.Server

프레임워크에서 제공하는 각 모듈들이 절대경로로 들어가 있어서 서버에서 돌고 있는 java 프로세스들을 확인하기 위해 ps -ef | grep java 만 하더라도 짜증이 솟구치게 된다.

그래서 Python으로 작성된 구동 스크립트에서 classpath를 환경변수로 떼버리도록 살짝 고쳤다.

$PLAY/framework/pym/play/utils.py 파일에 추가

def detach_classpath(cmd):
  i = cmd.index('-classpath')
  classpath = cmd[i+1]
  del cmd[i+1]
  del cmd[i]
  env = os.environ
  env['CLASSPATH'] = classpath
  return cmd

이제 $PLAY/framework/pym 에서

$ grep -rn "subprocess.Popen" play/commands
./play/commands/base.py:139:        process = subprocess.Popen(java_cmd, env=os.environ)
./play/commands/base.py:214:        play_process = subprocess.Popen(java_cmd, env=os.environ, stdout=sout)
./play/commands/daemon.py:47:        pid = subprocess.Popen(app.java_cmd(args), stdout=sout, env=os.environ).pid
./play/commands/daemon.py:90:        pid = subprocess.Popen(java_cmd, stdout=sout, env=os.environ).pid

로 검색하여 각 Popen 첫번째 인자를 아래와 같이 detach_classpath로 묶어준다.

subprocess.Popen(detach_classpath(app.java_cmd(args)), stdout=sout, env=os.environ).pid

detach_classpath 함수의 목표는 java_cmd 리스트에서 -classpath 다음 요소를 찾아 os.environ[‘CLASSPATH’]에 넣고 원래 list에서는 이를 지워버리는 것이다. os.environ을 런타임에 조작하는 애드혹 패치를 저지르긴 했지만 child process에게 넘겨질 os.environ을 수정하는 것이므로 별다른 문제는 없다.

Categories
Daily Life productivity

에너지

우울해서 무기력해졌다면 모를까, 천진반의 기공포처럼 기력을 정말 다 써서 무기력해진 경우라면 쉬면서 몸조리를 잘 하는 것 외에 별 다른 방법이 없다.

그러나 써야할 기력을 쓰지 못해서 무기력해진 경우도 많다. 주중에 생업에 너무 치여서 주말에 하고 싶은 다른 일을 할 기력이 전혀 남아있지 않다고 속단하지 마시길. 균형을 맞추기 위해서는 많아진 쪽을 줄이는 방법 말고도 적은 쪽을 늘리는 방법도 있다. 시간 끌지 말자.

 

 

Categories
Development productivity

생업에 치이느라 Java 7의 NIO.2에 관심없던 분들을 위한

Java 7 에 java.nio.file 패키지가 들어왔다.

java.io.File은 OS 에서 제공하는 다양한 파일시스템 특성들을 대부분 무시했기 때문에 쉘스크립트에서 $ cp src /path/to/dest 면 끝날 것을 꽤나 긴 코드를 쓰거나 commons-io FileUtils.copyFile 따위를 써야했었는데 이제는 java.nio.file.Files.copy(Path src, Path dest, CopyOption option)으로 작업을 마칠 수 있다. java.nio.file.Files.move의 CopyOption은 자바답지 않게 무려 ATOMIC_MOVE를 지원하는데 이는 Windows OS인 경우 MoveFileEx 콜이고, Linux/Solaris의 경우 rename(2) 콜이라, 동일 파티션 내의 큰 파일을 옮기더라도 광속이다.

Python의 open(‘.vimrc’).readlines() 과 동일한 작업을 하는 Files.readAllLines(Path, Charset) 도 반겨줄만하다.

이전에는 특정 디렉토리 밑의 모든 파일들에 대한 처리를 하기 위해 재귀호출을 하는 수고를 피할 수 없었는데 Files.walkFileTree(Path, FileVisitor<T>)를 통해 아래와 같이 간단히 처리할 수 있다.

import java.nio.file.*;
import java.nio.file.attribute.*;
...
    FileSystem fs = FileSystems.getDefault();
    Files.walkFileTree(fs.getPath("./rust-0.1/"), new SimpleFileVisitor() {
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
            throws IOException {
            System.out.println(file);
            return FileVisitResult.CONTINUE;
        }
    });

마지막으로 언급하지 않을 수 없는 WatchService ! 파일시스템 이벤트들을 받을 수 있다. 예를들어 특정 디렉토리 속에 임의의 파일이 생기고 지워지는 등의 각종 이벤트들 말이다. 리눅스의 경우 inotify_add_watch(2) poll(2) 콜이고, 솔라리스는 <port.h> 속의 각종 port_create, port_associate, port_send 등이며, 윈도우즈는 kernel32.dll의 ReadDirectoryChanges 콜이다. WatchService를 잘 활용한다면 개발환경 품질 향상을 꾀할 수 있다. 상상은 각자 알아서.

NIO.2 소개는 여기까지다.