SW 개발
- Ubuntu에 LAMP 설치 2013.10.09
- svn 프로젝트 삭제 2013.10.03
- trac-admin 사용 2013.09.29
- Amazon AWS 우분투 기반 Trac & Subversion 2013.09.18 1
- Putty를 통해 Amazon AWS Windows에서 접속 2013.09.18
- WM_INPUT 메시지 핸들링 2013.08.21
- Java 7의 새로운 특징 : Java7에서의 중요한 변화들과 업데이트된 항목에 대한 조사. 2013.02.01
- Amazon EC2 Cloud 사용하기 2013.01.30
- MFC 컴파일 시 fatal error C1010 2013.01.16
- 18장 깜빡임 방지 2013.01.09
Ubuntu에 LAMP 설치
svn 프로젝트 삭제
svn delete -m "Deleting project dir" http://xxx.xxx.xxx.xxx/svn/project/asdf
trac-admin 사용
sudo trac-admin <프로젝트경로>
ex> sudo trac-admin /var/trac/sak2013
이렇게 하면 해당 프로젝트에 대해 trac-admin이 실행된다.
help 만 입력하면 각 명령어들에 대한 간략한 설명을 볼 수 있고
'help 명령어'와 같은 식으로 입력하면 해당 명령어에 대한 자세한 설명을 볼 수 있다.
예>
Amazon AWS 우분투 기반 Trac & Subversion
아래 내용 참고하여 환경을 구성했고
나는 제일 처음에 아래 두 명령을 먼저 수행했음
$ sudo apt-get update
$ sudo apt-get upgrade
trac 및 svn 사용자 추가는 아래와 같이 했음
$ sudo htdigest /etc/apache2/.htdigest Repository <User ID>
$ sudo htdigest /etc/apache2/.htdigest Trac <User ID>
-------------------------------------------------------------------------------------------------
1. TRAC Package 설치.
1. 아파치 웹서버 설치
Trac을 웹서버없이 단독으로 올릴 수는 있지만 그리 권장할 만 하지는 않다.
그리고 Ubuntu Desktop에는 아파치 웹서버가 기본설치되지 않기 때문에 다음과 같이 설치해야 한다.
$ sudo apt-get install apache2
.
2. Subversion 설치
Trac은 서브버전과 통합된 형태이기 때문에 Subversion도 설치해야 한다.(svn 1.5.1 이 설치됨)
$ sudo apt-get install subversion libapache2-svn
3. Trac 설치
Trac은 최신버전인 0.11 이 설치된다.
$ sudo apt-get install trac libapache2-mod-python python-setuptools
우선 간단하게 apt-get 명령어로 TRAC 및 Subveersion을 설치합니다. 이때 Subversion은 TRAC에서 필요로 하므로 의존성 검사로 인해 알아서 설치합니다
2. SVN 환경설정
우선 저장소 역할을 할 Directory를 만들도록 합니다. 일단 여기서는 나중에 추가로 설명할 Apache와의 연동을 위해/var/svn을 합니다만 굳이 /var/svn에 하실 필요는 없으시고 원하시는 위치에 만드셔도 상관은 없습니다. 단 연동을 위해 필요한 사용자 계정으로 www-data(필요하면 다른 계정을 설정해도 상관없지만요)를 통해 이뤄지기 때문에, 저장소에 대한 사용자 권한을 www-data가 갖도록 했습니다. 이는 뒤에 나오는 TRAC에서도 마찬가지로 설정 했습니다.
1: sudo mkdir /var/svn
2: sudo chown www-data.www-data /var/svn
3: sudo -u www-data svnadmin create /var/svn/<Project Name>
이때 /var/svn은 저장소의 부모 디렉토리이며, 실제 저장소를 프로젝트이름(<Project Name>)으로 생성하면 개별 프로젝트에 대한 저장소가 생성됩니다.
이후 새로운 프로젝트를 등록하고 싶으면 3번 줄의 부분만 반복적으로 수행해 주면 됩니다.
3. TRAC 환경 설정
TRAC도 SVN과 같이 디렉토리를 구성하면 됩니다.
1: sudo mkdir /var/trac
2: sudo chown www-data.www-data /var/trac
위와 같이 디렉토리를 생성하면 TRAC에 대한 메인 디렉토리가 생성됩니다.
1: sudo -u www-data trac-admin /var/trac/<Project Name> initenv # 초기생성용
2: sudo -u www-data trac-admin /var/trac/<Project Name> upgrade # 마이그레이션용
이제 TRAC을 설치하도록 하겠습니다. 기본적으로 2가지 명령어가 있는데 위와 같이 끝에 initenv를 해서 새로운 프로젝트를 생성하고, 그렇지 않고 TRAC이 버젼업 되었다던가 다른 이유로 마이그레이션이 필요하면 아래와 같이 upgrade를 수행합니다. 수행하면 총 4개의 위와 같은 질문을 하는데 내용은 아래와 같고 각각 그에 맞는 값을 설정합니다.
1: Project Name [My Project]> <Project Name>
2: Database connection string [sqlite:db/trac.db]>
3: Repository type [svn]>
4: Path to repository [/path/to/repos]> /var/svn/<Project Name>
1 .프로젝트 명: 원하는 프로젝트 이름을 넣습니다. 이름은 SVN과 맞춰줄 필요는 없습니다.
2. DB 연결명: 아직 설정해 본적이 없어서 모르겠지만 기본설정을 그대로 둡니다.
3. 저장소 종류: SVN말고도 여러가지 있는데 여기서는 Subversion을 사용한 관겨로 기본값으로 그대로 둡니다.
4. 저장소 위치: 앞서 만든 저장소의 위치를 입력합니다.
4. TRAC 관리자 계정 추가
마지막으로 TRAC을 관리할 관리자 계정을 추가합니다. 이는 내일 다시 올릴 Apache와의 연동할 때 필요한 부분입니다.
1: sudo -u www-data trac-admin /var/trac/<Project Name> permission add <User ID> TRAC_ADMIN
이렇게 하면 간단히 TRAC ‘자체’에 대한 설정이 끝나게 됩니다. 하지만 정작 사람들이 잘 써먹고 있는 웹화면상의 TRAC으로 갈려면 Apache와 연동을 해야 하는 부분이 남아 있습니다.
5. Apache 및 관련 Package 설치.
우선 연동 하기에 앞서 Apache 및 관련 모듈을을 설치해야 합니다. 따라서 apache2-threaded-dev, libapache2-mod-python, python-dev, libapache2-svn 정도만 설치하면 왠만한 모듈은 알아서 설치하게 됩니다.
1: sudo apt-get install apache2-threaded-dev libapache2-svn
2: sudo apt-get install libapache2-mod-python python-dev
1. Apache에 SVN과 TRAC을 연동
우선 이부분을 하기에 앞서 SVN과 TRAC의 사용방법은 가지 각색이겠지만 2가지가 있습니다.(일단 제 기준 입니다.)
• 1개의 SVN과 TRAC의 프로젝트를 만들고 그 안에서 모든 프로젝트들을 관리한다.
o장점: 많은 프로젝트를 다 같이 할 때 한번에 모니터링이 가
o단점: 각 프로젝트에 대한 관리가 뒤섞일 수 있음.
o권장: 여러 간단한 작업들로만 있는 경우 권장.
•개별 프로젝트마다 SVN과 TRAC의 프로젝트를 생성. 독립적으로 관리한다.
o장점: 각각 프로젝트마다 관리 하기 때문에 뒤섞일 일이 적고 계정 권한 관리가 쉽다.
o단점: 여러 프로젝트에 대해 각각 관리하기 때문에 손이 많이 가고 한번에 모든 모니터링이 불편(?)
o권장: 개별 프로젝트 들이 덩치가 큰 경우, 장기 프로젝트 등….
일단 이번에는 2번째 항목인 개별 프로젝트마다의 SVN과 TRAC을 생성해 관리하도록 하는 기능으로 설명하겠습니다. 나머지는 주석 처리한 부분을 푸시고 원래 있던 동급의 내용에 주석처리 하시면 됩니다. ^^
5. SVN 올리기
우선 /etc/apache2/mods-available/dav_svn.conf 파일을 열고(없으면 만들면 됩니다.) 다음을 추가 합니다.
1: <Location /svn>
2: DAV svn
3:
4: # /var/svn/ 으로 저장소의 부모폴더로 연결합니다
5: SVNParentPath /var/svn
6: # 단 1개의 프로젝트만 사용하면 아래와 같이 SVNPath를 대신 입력합니다
7: #SVNPath /var/svn/<Project Name>
8:
9: # Digest 인증 설정
10: AuthType Digest
11: AuthName "Repository"
12: AuthUserFile /etc/apache2/.htdigest
13:
14: # Basic 인증 설정
15: # JAVA 기반 프로그램들 에서는 Digest인증을 하면
16: # Export와 checkout을 못하는 기현상이 일어 나더군요
17: # 이런 경우 사용해 주세요
18: #AuthType Basic
19: #AuthName "Repository"
20: #AuthUserFile /etc/apache2/.htpasswd
21:
22: # Commit 의 접근 억세스 설정
23: <LimitExcept REPORT>
24: Require valid-user
25: </LimitExcept>
26: </Location>
단 이경우 내용에도 써 있지만 SVNPath와 SVNParentPath는 용도에 따라 둘중 하나만 사용할 수 있습니다. 또 왜인지는 모르겠는데 JAVA 기반인 경우에서는 Digest 인증을 못하더라고요. 그런관계로 이경우에는 어쩔 수 없이 Basic 인증을 사용하면 됩니다. (C 기반 SVN Client는 잘 돌아갑니다.) 일단 인증 파일로 각각 Digest의 경우 /etc/apache2/.htdigest로 Basic의 경우 /etc/apache2/.htpasswd로 했습니다. 각각 만드는 법에 대해서는 Digest만 뒤에 올려두도록 하겠습니다.
이제 Module 설정 파일을 만들었으니 apache에 올리도록 합니다. 올리는 방법은 아래와 같이 사용하면 됩니다.
1: sudo a2enmod dav_svn
2: sudo a2enmod auth_digest
6. TRAC 올리기
TRAC도 마찬가지 방법으로 작성을 해야 합니다. 우선 /etc/apache2/sites-available/trac을 다음과 같이 작성합니다.
1: # 하나의 TRAC에서 모든 프로젝트를 사용할 때 쓰는 Alias 입니다.
2: #Alias /trac /var/trac/<Project Name>
3:
4: <Location /trac>
5: SetHandler mod_python
6: PythonHandler trac.web.modpython_frontend
7: # TRAC의 부모 디렉토리 설정. 개별 프로젝트마다 TRAC을 사용할 때 씁니다
8: PythonOption TracEnvParentDir /var/trac
9: # TRAC 프로젝트 설정. 모든 프로젝트를 하나의 TRAC에서 사용할 때 씁니다
10: #PythonOption TracEnv /var/trac/<Project Name>
11: PythonOption TracUriRoot /trac
12:
13: # Digest 인증 설정
14: AuthType Digest
15: AuthName "Trac"
16: AuthUserFile "/etc/apache2/.htdigest"
17: Require valid-user
18:
19: # Basic 인증 설정
20: # 앞선 svn 설정과 계정을 맞춰주기 위해 Basic 설정을 쓰는 경우 사용
21: #AuthType Basic
22: #AuthName "Repository"
23: #AuthUserFile /etc/apache2/.htpasswd
24: </Location>
내용은 SVN을 설정 했을 때와 마찬가지 입니다. 이번에도 마찬가지로 PythonOption으로 준 TracEnvParanetDir과 TracEnv는 둘중에 하나만 사용해야 합니다. 또한 Apache에 적용하기 위해서 다음 명령어로 TRAC을 추가합니다.
1: sudo a2ensite trac
7. TRAC 사용자 계정 설정.
우선 이번글에서는 Digest 설정하는 부분만 넣도록 하겠습니다. 일단 Digest를 위한 사용자의 암호를 넣어야 하는데요. 각각SVN과 TRAC을 위해 구분시켜서 넣도록 합니다. 단 앞서 올린 포스트에 설정한 관리자 계정도 반드시 포함되어야 합니다!!
1: user@user-pc:/etc/apache2$ sudo htdigest -c /etc/apache2/.htdigest Repository <User ID>
2: Adding password for user in realm Repository.
3: New password:
4: Re-type new password:
5: user@user-pc:/etc/apache2$ sudo htdigest /etc/apache2/.htdigest Trac <User ID>
6: Adding user user in realm Trac
7: New password:
8: Re-type new password:
9: user@user-pc:/etc/apache2$ sudo chmod 600 /etc/apache2/.htdigest
10: user@user-pc:/etc/apache2$ sudo chown www-data.www-data /etc/apache2/.htdigest
8. Apache 사용자 추가
1. 사용자 정보 수정
비밀번호 수정 : htpasswd -m /etc/apache2/dav_svn.passwd 사용자 ID
새 사용자 생성 : htpasswd -c /etc/apache2/dav_svn.passwd 새로운 사용자 ID
2. 재시작
많은 분들이 알고 계시리라 믿습니다만 혹시나 해서 추가합니다.
sudo /etc/init.d/apache2 restart
마지막에 /var/svn 과 /var/trac 폴더에 퍼미션을 주어야 제대로 접속이됨
이걸로 SVN과 Trac을 Apache에 연결시켜서 설정하는 방법 까지 끝났습니다. 이제 남은 것은 TRAC과 SVN을 사용하는 것 뿐이로군요. 실제 접근할 때 필요한 주소들은…
• TRAC: http://<사용하는 웹 주소>/trac
• SVN 저장소: http://<사용하는 웹 주소>/svn/<Project Name>
해서 사용하시면 됩니다. 실제 화면은 직업 확인해 보세요.. ^^
9. SVN 사용법
1. 용어 설명
저장소
리포지토리(Repository)라고도 하며 모든 프로젝트의 프로그램 소스들은 이 저장소 안에 저장이 됩니다. 그리고 소스뿐만이 아니라 소스의 변경 사항도 모두 저장됩니다. 네트워크를 통해서 여러 사람이 접근 할 수 있습니다. 버전 관리 시스템 마다 각각 다른 파일 시스템을 가지고 있으며 Subversion은 Berkeley DB를 사용합니다. 한 프로젝트 마다 하나의 저장소가 필요합니다.
리비전(Revision)
소스 파일등을 수정하여 커밋하게 되면 일정한 규칙에 의해 숫자가 증가 합니다. 저장소에 저장된 각각의 파일 버전이라 할 수 있습니다. Subversion의 경우 파일별로 리비전이 매겨지지 않고 한번 커밋 한 것으로 전체 리비전이 매겨 집니다. 리비전을 보고 프로젝트 진행 상황을 알 수 있습니다.
trunk
단어 자체의 뜻은 본체 부분, 나무줄기, 몸통 등 입니다. 프로젝트에서 가장 중심이 되는 디렉토리입니다. 모든 프로그램 개발 작업은 trunk 디렉토리에서 이루어집니다. 그래서 위의 구조에서 trunk 디렉토리 아래에는 바로 소스들의 파일과 디렉토리가 들어가게 됩니다.
Branches
나무줄기(trunk)에서 뻗어져 나온 나무 가지를 뜻합니다. trunk 디렉토리에서 프로그램을 개발하다 보면 큰 프로젝트에서 또 다른 작은 분류로 빼서 따로 개발해야 할 경우가 생깁니다. 프로젝트안의 작은 프로젝트라고 생각하면 됩니다. branches 디렉토리 안에 또 다른 디렉토리를 두어 그 안에서 개발하게 됩니다.
Tags
tag는 꼬리표라는 뜻을 가지고 있습니다. 이 디렉토리는 프로그램을 개발하면서 정기적으로 릴리즈를 할 때 0.1, 0.2, 1.0 하는 식으로 버전을 붙여 발표하게 되는데 그때그때 발표한 소스를 따로 저장하는 공간입니다. 위에서 보면 tags 디렉토리 아래에는 버전명으로 디렉토리가 만들어져 있습니다.
2. 명령어 의미
Import : svn import sampledir svn+ssh://svn-domain/svn/sample/trunk
맨 처음 프로젝트 시작할때 저장소에 등록하는 명령어 한 번 하고 나면 쓸일이 잘 없을 듯.
Checkout : svn checkout svn+ssh://svn-domain/svn/sample/trunk sample
저장소에서 소스를 받아 오는 명령어. 받아온 소스에는 소스 뿐만이 아니라 버젼관리를 위한 파일도 같이 받아 온다. 지우거나 변경시 저장소와 연결 불가능
Export : svn export svn+ssh://svn-domain/svn/sample2/trunk sample
체크아웃과는 달리 버젼관리 파일을 뺀 순수한 소스만 가져오는 명령어 마지막에 사용.
Commit : svn commit
체크아웃 한 소스를 수정, 파일 추가, 삭제 등을 한 뒤 저장소에 저장하여 갱신 하는 명령어. Revision이 1 증가 한다.
Update : svn update
체크아웃 해서 받은 소스를 최신의 소스로 업데이트 하는 명령어. 소스 수정이나 Commit 하기전에 한 번씩 해줘야 할 듯. 잘 못하면 소스 망치는 경우가 있을 듯.
Log : svn log
저장소에 어떠한 것들이 변경 되었는지 확인 할 수 있는 log 명령어
svn log // 전체 로그 확인
svn log trunk/main/main.c // trunk/main/main.c 로그확인
svn log trunk/memo //trunk/memo 로그 확인
svn log -r 2 // 리버전2 로그 확인
svn log -r 1:3 //리버전 1~3 까지 로그 확인
svn log -r 3:1 // 리버전 3~1 까지 로그 확인
로그 확인시 -v 옵션을 주면 좀더 자세한 정보를 출력하고 -q 옵션은 더 간단히 출력해 준다..
Diff : svn diff --revision 4 sample.c
diff 명령은 예전 소스 파일과 지금의 소스 파일을 비교해 보는 명령어
Blame : svn blame sample.c
Blame은 한 소스파일을 대상으로 각 리비전 대해서 어떤 행을 누가 수정했는지 알아보기 위한 명령어
lock : svn lock hello.c
파일에 락을 걸어 락을 건 사용자만이 수정할 수 있게 해주는 명령어. 해제는 svn unlock.
왜 파일에 락을 걸었는지 로그를 기록 할 수 있다.
Add : svn add hello.c
새 파일을 만들었을 경우에 파일을 추가 해주는 명령어.
그 뒤엔 꼭 svn commit를 꼭 해줘야 한다.
새 파일을 생성해서 올릴 때에도 꼭 add를 해줘야 함. 안해주면 commit을 해도 안 올라감.
Status : svn status
자신이 수정하고 있는 파일의 상태를 알려주는 명령어
Help : svn help
상세 사용법 출력. svn help subcommand 도 가능.
Add : svn add
새로 생성한 파일이나 디렉토리를 저장소에 추가 예약
Mkdir : svn mkdir
디렉토리 새로 생성
Delete : svn delete (del, remove, rm)
파일이나 디렉토리를 삭제 (로컬과 저장소 둘다)
Move : svn move (mv, rename, ren)
파일이나 디렉토리를 이동하거나 이름 변경
Copy : svn copy (cp)
파일이나 디렉토리 복사
3. 파일 백업및 복구
1. dump
sample 저장소를 백업합니다. 표준 입출력을 통해서 저장소의 내용을 파일로 생성합니다. svnadmin dump 명령을 사용하며 이 명령은 저장소 디렉토리 바깥에서 사용해야 합니다.
repos# ls
sample
repos# svnadmin dump sample > sample.dump
2. load
Load 하기 위해선 신규 Repository(sample)를 생성한다.
저장소 백업 파일을 이용해서 저장소를 복구합니다. svnadmin load 명령을 사용합니다.
빈 저장소를 생성한 뒤 백업 파일을 이용해서 복구를 합니다.
repos# svnadmin create sample
repos# ls
sample sample.dump
repos# svnadmin load sample < sample.dump
3. sync
svnsync는 1.4.0에서 새로 생긴 명령입니다. svnsync 명령을 이용해서 저장소를 그대로 복사해 올 수 있습니다. 단 복사해오고자 하는 원본 저장소가 Subversion 1.4 이상을 사용하고 있어야 하며 1.4 이하를 사용하고 있을 경우 svnsync명령이 동작하지 않습니다.
먼저 빈 저장소를 만듭니다.
# cd /home/svn/
/home/svn# svnadmin create syncsample
pre-revprop-change 파일을 실행할 수 있도록 권한을 조정합니다
/home/svn/syncsample/hooks# chmod 777 pre-revprop-change
svnsync를 사용할 수 있도록 저장소를 초기화 합니다. file:///home/svn/syncsample은 방금 만든 빈 저장소 경로이고http://svn.collab.net/repos/svn은 복사해 올 원본 저장소의 주소입니다. http://, svn://등 접속 가능한 저장소 주소이면 되고 trunk나 branches같은 디렉토리가 아닌 최 상위 디렉토리의 주소로 설정해줘야 합니다.
/home/svn# svnsync init file:///home/svn/syncsample http://svn.collab.net/repos/svn
Copied properties for revision 0.
이제 저장소를 복사를 시작합니다.
/home/svn# svnsync sync file:///home/svn/syncsample
Committed revision 1.
Copied properties for revision 1.
Committed revision 2.
Copied properties for revision 2.
Committed revision 3.
Copied properties for revision 3.
Committed revision 4.
Copied properties for revision 4.
Committed revision 5.
Copied properties for revision 5.
Committed revision 6.
Copied properties for revision 6.
....
최신 리비전 까지 복사해오면 svnsync 명령이 끝난 것입니다.
이제 이 저장소에서 소스를 체크아웃 하여 살펴볼 수 있습니다.
5. Svnserve에서 ID로 사용자 인증
Subversion 0.33.0버전 이후부터 svnserve로 ID로 사용자 인증이 가능하게 되었습니다. 그 이전 버전에서 svnadmin으로 저장소를 만들면 저장소 디렉토리 아래에 conf 디렉토리가 생기지 않지만 0.33.0 버전이후에 svnadmin으로 저장소를 만들었다면 저장소 디렉토리 아래에 conf 디렉토리가 자동으로 생성됩니다. 이전 버전에서 먼저 저장소를 만들어 두었다면 저장소 디렉토리 /home/svn/sample 아래 conf 디렉토리를 만들어 줍니다. (/home/svn/sample/conf)
이제 각 저장소 디렉토리 아래 conf 디렉토리가 있습니다. /home/svn/sample/conf/svnserve.conf 파일이 svnserve의 설정 파일입니다. 0.33.0 버전 이전 만든 저장소에는 conf 디렉토리 및 svnserve.conf 파일이 없습니다. 그럴 경우에는 conf 디렉토리와 svnserve.conf 파일을 만들어 주면 됩니다.
svnserve.conf 파일을 아래와 같이 설정 합니다.
### This file controls the configuration of the svnserve daemon, if you
### use it to allow access to this repository. (If you only allow
### access through http: and/or file: URLs, then this file is
### irrelevant.)
### Visit http://subversion.tigris.org/ for more information.
[general]
### These options control access to the repository for unauthenticated
### and authenticated users. Valid values are "write", "read",
### and "none". The sample settings below are the defaults.
anon-access = none
auth-access = write
### The password-db option controls the location of the password
### database file. Unless you specify a path starting with a /,
### the file's location is relative to the conf directory.
### The format of the password database is similar to this file.
### It contains one section labelled [users]. The name and
### password for each user follow, one account per line. The
### format is
### USERNAME = PASSWORD
### Please note that both the user name and password are case
### sensitive. There is no default for the password file.
password-db = passwd
### This option specifies the authentication realm of the repository.
### If two repositories have the same authentication realm, they should
### have the same password database, and vice versa. The default realm
### is repository's uuid.
realm = pyrasis's Repository
anon-access = none으로 아무에게나(Anonymous) 저장소에 접근하는 것을 막았습니다. read로 하면 읽기만 가능하며 write로 해주면 읽고 쓰기가 가능해집니다.
auth-access = write는 ID로 인증된 사용자에게 쓰기 권한을 주는 것입니다.
password-db = passwd 이 설정은 svnserve의 패스워드 파일입니다 이전의 Apache 패스워드 파일과는 별개입니다. 아래 내용으로 /home/svn/sample/conf 아래 passwd 라는 이름으로 만듭니다. ID = 패스워드 형식 입니다. 아직 암호화된 패스워드는 지원하지 않는 것 같습니다. 버전 업을 통해 개선 될 것 같습니다.
passwd
[users]
sampleuser = 02030104[출처] SVN 서버 구축 & Trac 설치방법 및 사용법|작성자 미니187
Putty를 통해 Amazon AWS Windows에서 접속
http://jmkook77.blogspot.kr/2012/01/putty.html
아마존 서버 생성시 다운받은 pem 파일을 이용하여 ssh/sftp 접속하는 방법
1. putty 를 다운받습니다.
http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html
여기에서 putty<version>-installer.exe 를 받으세요.
혹은, putty.exe, psftp.exe, puttygen.exe, pageant.exe 를 따로 설치하셔도 됩니다.
puttygen.exe 는 pem 파일을 putty에서 사용가능하게 변경하며
pageant.exe 는 pem 파일을 통해 putty, psftp 가 서버에 접속 가능하게 해줍니다.
2. pem 파일 변환
1) puttygen.exe 를 실행하면 아래와 같은 화면이 뜹니다. 상단의 Conversions / Import Key 를 선택합니다.
2) 해당 서버에 접속하기 위한 pem파일을 선택합니다.
3) 아래와 같이 정상적으로 로드가 된것을 확인할 수 있습니다.
이제 하단 우측에 있는 Save private key 를 선택하고 Yes 를 선택합니다.
4) 원하는 위치에 파일명을 설정하여 ppk 파일을 저장합니다. ppk 파일 생성 완료!!
2. Pageant.exe 를 실행하면 아래와 같이 윈도우 우측 하단에 트레이로 추가된것을 확인할 수 있습니다. 이녀석은 항상 저곳에 있어야만 합니다.
2) 위에서 저장한 ppk 파일을 선택해줍니다.
3) 아래와 같이 정상적으로 추가된것을 확인할수 있습니다. 이제 해당 창을 닫습니다.
2) 최초 접속시 해당 얼럿이 뜰겁니다. Yes 를 누릅니다.
4. Psftp.exe 를 실행합니다. ( 당연히 이놈도 Pageant 가 실행되어있어야 겠죠? )
역시 계정에 root 를 입력하여 정상 접속되는 것을 확인할 수 있습니다.
기념으로 이미지하나는 드래그하여 put 해봅니다.
끝!!
WM_INPUT 메시지 핸들링
종료할 때 EndEventCapture() 호출
StartEventCapture() 호출하면 WM_INPUT 메시지가 발생함
GetRawInputData를 사용해서 키보드, 마우스 이벤트를 가져오면 됨.
void StartEventCapture() { RAWINPUTDEVICE rawInputDev[2]; ZeroMemory(rawInputDev, sizeof(RAWINPUTDEVICE)*2); // 키보드 RAWINPUTDEVICE 구조체 설정 rawInputDev[0].usUsagePage = 0x01; rawInputDev[0].usUsage = 0x06; rawInputDev[0].dwFlags = RIDEV_INPUTSINK; rawInputDev[0].hwndTarget = GetSafeHwnd(); //마우스 RAWINPUTDEVICE 구조체 설정 rawInputDev[1].usUsagePage = 0x01; rawInputDev[1].usUsage = 0x02; rawInputDev[1].dwFlags = RIDEV_INPUTSINK; rawInputDev[1].hwndTarget = GetSafeHwnd(); if( FALSE == RegisterRawInputDevices(rawInputDev, 2, sizeof(RAWINPUTDEVICE)) ) { CString str; str.Format(_T("RegisterRawInputDevices Error %d"), GetLastError()); MessageBox(str); } } void EndEventCapture() { RAWINPUTDEVICE rawInputDev[2]; ZeroMemory(rawInputDev, sizeof(RAWINPUTDEVICE)*2); // 키보드 RAWINPUTDEVICE 구조체 설정 rawInputDev[0].usUsagePage = 0x01; rawInputDev[0].usUsage = 0x06; rawInputDev[0].dwFlags = RIDEV_REMOVE;// <== 이부분이 틀림 rawInputDev[0].hwndTarget = GetSafeHwnd(); //마우스 RAWINPUTDEVICE 구조체 설정 rawInputDev[1].usUsagePage = 0x01; rawInputDev[1].usUsage = 0x02; rawInputDev[1].dwFlags = RIDEV_REMOVE;// <== 이부분이 틀림 rawInputDev[1].hwndTarget = GetSafeHwnd(); if( FALSE == RegisterRawInputDevices(rawInputDev, 2, sizeof(RAWINPUTDEVICE)) ) { CString str; str.Format(_T("RegisterRawInputDevices Error %d"), GetLastError()); MessageBox(str); } } LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { // TODO: 여기에 특수화된 코드를 추가 및/또는 기본 클래스를 호출합니다. if( message == WM_INPUT ) { UINT dwSize = 40; static BYTE lpb[40]; GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)); RAWINPUT* raw = (RAWINPUT*)lpb; if( raw->header.dwType == RIM_TYPEMOUSE ) { int xPosRelative = raw->data.mouse.lLastX; int yPosRelative = raw->data.mouse.lLastY; if( raw->data.mouse.ulButtons == 0 ) // move { InvalidateRect(CRect(0,50,150,100)); } else if( raw->data.mouse.ulButtons == 1 /*|| m_bLbuttonDragging*/ ) // l-button down { } else if( raw->data.mouse.ulButtons == 2 ) // l-button up { } else if( raw->data.mouse.ulButtons == 4 ) // r-button down { } else if( raw->data.mouse.ulButtons == 8 ) // r-button down { } else { } } if( raw->header.dwType == RIM_TYPEKEYBOARD ) { CString str; str.Format( _T(" Kbd: make=%04x Flags:%04x Reserved:%04x ExtraInformation:%08x, msg=%04x VK=%04x \n"), raw->data.keyboard.MakeCode, raw->data.keyboard.Flags, raw->data.keyboard.Reserved, raw->data.keyboard.ExtraInformation, raw->data.keyboard.Message, raw->data.keyboard.VKey); MSG msg; memset( &msg, 0, sizeof(MSG) ); msg.hwnd = m_hWnd; msg.message = raw->data.keyboard.Message; msg.wParam = raw->data.keyboard.VKey; // KeyMessageProcessing( &msg ); OutputDebugString( str ); } } return CDialog::WindowProc(message, wParam, lParam); }
Java 7의 새로운 특징 : Java7에서의 중요한 변화들과 업데이트된 항목에 대한 조사.
Amazon EC2 Cloud 사용하기
MFC 컴파일 시 fatal error C1010
MFC 컴파일 시에 아래와 같은 에러가 발생할 때가 있다.
"fatal error C1010: 미리 컴파일된 헤더를 찾는 동안 예기치 않은 파일의 끝이 나타났습니다. '#include "stdafx.h"'을(를) 소스에 추가하시겠습니까?"
Precompiled Header 때문에 발생하는 에러이다.
자세한 내용 및 해결 방안은 아래 링크 참조
18장 깜빡임 방지
- 화면 그리기의 구조
- CWnd::RedrawWindow()
- WM_PAINT 메시지를 발생시켜 윈도우를 다시 그리도록 한다. - 윈도우의 크기를 변경하여 빠른 속도로 윈도우가 다시 그려지도록 하면 화면이 깜빡이거나 현상 발생
- WM_ERASEBKGND 메시지
- WM_PAINT 메시지와 더불어 윈도우를 다시 그릴 때 발생
- WM_ERASEBKGND 메시지 핸들러 함수는 윈도우의 배경을 그리는 코드 수행
- 클라이언트 영역을 다시 그릴 때 WM_PAINT 메시지에 앞서 WM_ERASEBKGND 메시지 발생
(비클라이언트 영역을 다시 그리는 메시지는 WM_NCPAINT)
- 윈도우가 깜빡이는 주요 원인 중 하나
- WM_ERASEBKGND 메시지 핸들러 함수를 등록하여 상위 클래스의 멤버를 호출하지 않도록 하면 깜박임이 줄어듬 - 눈속임의 미학
- 클라이언트 뷰의 자식 윈도우로 있는 윈도우가 배경을 그릴 때(WM_ERASEBKGND 메시지가 발생했을 때) 자신의 부모 윈도우의 OnEraseBkgnd() 메시지 핸들러 함수를 명시적으로 호출하여 배경 이미지 획득 후 이미지 출력하여 투명해 보이는 효과 얻음
- 클라이언트 뷰의 OnEraseBkgnd() 함수
- 전달받은 DC에 이미지를 로드하여 출력 - 클라이언트 뷰의 자식 윈도우의 OnEraseBkgnd() 함수
- 메모리 DC에 부모 윈도우의 배경을 획득 후 자식 윈도우에 출력 - 더블 버퍼링(Double Buffering)
- 윈도우의 깜빡임을 제거하는 최선의 방법
- 메모리 DC(버퍼 DC)에 모든 그리기 작업을 수행한 후, 메모리 DC의 내용을 화면 DC로 복사하는 기법
- 그리는 과정이 화면에 출력되지 않으므로 깜빡임이 사라짐
- CBufferDC 클래스
- BufferDC.h - WM_ERASEBKGND 메시지 핸들러 함수를 등록하여 아무런 처리도 하지 않도록 코드를 수정하고 OnPaint() 함수에서 CBufferDC 클래스를 활용하여 더블 버퍼링을 구현한다면 화면 깜빡임을 완벽히 해결할 수 있음
- 1.(3) 참조
BOOL CRedrawDemoView::OnEraseBkgnd(CDC* pDC) { return TRUE; // return CView::OnEraseBkgnd(pDC); }
- 위 기법과 더블 버퍼링을 함께 사용하면 깜빡임이 전혀 없는 인터페이스를 구현 가능
BOOL CTransparentDemoView::OnEraseBkgnd(CDC* pDC) { CRect Rect; GetClientRect(&Rect); pDC->FillSolidRect(&Rect, RGB(255, 255, 255)); CImage ImageBackground; ImageBackground.LoadFromResource(AfxGetInstanceHandle(), IDB_Background); ImageBackground.BitBlt(pDC->m_hDC, 0, 0); return TRUE; // return CView::OnEraseBkgnd(pDC); }
BOOL CTransparentWnd::OnEraseBkgnd(CDC* pDC) { // 자식 윈도우의 왼쪽 위가 부모 윈도우 기준으로 어딘지 좌표 계산 CRect Rect, ParentRect; GetClientRect(&Rect); GetParent()->GetClientRect(&ParentRect); CPoint ptLeftTop = CPoint(0, 0); ClientToScreen(&ptLeftTop); GetParent()->ScreenToClient(&ptLeftTop); // 메모리 DC에 적절한 CBitmap 클래스 객체 생성하여 선택 CDC MemDC; CBitmap Bmp; MemDC.CreateCompatibleDC(NULL); Bmp.CreateBitmap(ParentRect.Width(), ParentRect.Height(), MemDC.GetDeviceCaps(PLANES), MemDC.GetDeviceCaps(BITSPIXEL), NULL); CBitmap* pOldBmp = MemDC.SelectObject(&Bmp); // 메모리 DC의 핸들을 메시지 파라미터로 부모 윈도우에 WM_ERASEBKGND 메시지 송신 GetParent()->SendMessage(WM_ERASEBKGND, (WPARAM)MemDC.m_hDC); pDC->BitBlt(0, 0, Rect.Width(), Rect.Height(), &MemDC, ptLeftTop.x, ptLeftTop.y, SRCCOPY); MemDC.SelectObject(pOldBmp); return TRUE; // return CWnd::OnEraseBkgnd(pDC); }
class CBufferDC : public CDC { private: CBufferDC() { } CBufferDC(const CBufferDC &src) { } CBufferDC& operator=(const CBufferDC &src) { } protected: BOOL Attach(HDC hDC); HDC Detach(); private: CWnd* m_pParent; //대상 윈도우에 대한 포인터 CDC* m_pTarget; //대상 윈도우 DC에 대한 포인터 PAINTSTRUCT m_PaintStruct; CRect m_RcClient, m_RcWindow; //대상 윈도우의 크기 정보 CDC m_MemoryDC; //버퍼 DC CBitmap m_MemoryBmp, *m_pOldMemoryBmp; //버퍼링을 위한 비트맵 public: CBufferDC(CWnd *pParent); ~CBufferDC(); public: inline CRect ClientRect() const { return m_RcClient; } inline CRect WindowRect() const { return m_RcWindow; } inline CRect UpdateRect() const { return m_PaintStruct.rcPaint; } operator HDC() const { return m_MemoryDC.m_hDC; } // DC handle for API functions };
- BufferDC.cpp
////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CBufferDC::CBufferDC(CWnd *pParent) : m_pParent(pParent) { ASSERT(pParent); //대상 윈도우에 대한 정보를 수집한다. m_pTarget = m_pParent->BeginPaint(&m_PaintStruct); m_pParent->GetClientRect(&m_RcClient); m_pParent->GetWindowRect(&m_RcWindow); //대상 윈도우에 대한 DC를 생성한다. m_MemoryDC.CreateCompatibleDC(m_pTarget); //대상 DC에 대한 메모리 비트맵을 생성하여 Select 한다. m_MemoryBmp.CreateBitmap(m_RcClient.Width(), m_RcClient.Height(), m_MemoryDC.GetDeviceCaps(PLANES), m_MemoryDC.GetDeviceCaps(BITSPIXEL), 0); m_pOldMemoryBmp = m_MemoryDC.SelectObject(&m_MemoryBmp); //메모리 버퍼에 Attach한다. Attach(m_MemoryDC); } ////////////////////////////////////////////////////////////////////// CBufferDC::~CBufferDC() { //메모리 DC의 내용을 대상 윈도우에 출력한다. //내부적으로 비트맵에 출력한 것이므로 해당 비트맵을 1:1로 복사한다. m_pTarget->BitBlt( m_PaintStruct.rcPaint.left, m_PaintStruct.rcPaint.top, m_PaintStruct.rcPaint.right - m_PaintStruct.rcPaint.left, m_PaintStruct.rcPaint.bottom - m_PaintStruct.rcPaint.top, &m_MemoryDC, m_PaintStruct.rcPaint.left, m_PaintStruct.rcPaint.top, SRCCOPY); m_MemoryDC.SelectObject(m_pOldMemoryBmp); m_pParent->EndPaint(&m_PaintStruct); Detach(); } ////////////////////////////////////////////////////////////////////// BOOL CBufferDC::Attach(HDC hDC) { return CDC::Attach(hDC); } ////////////////////////////////////////////////////////////////////// HDC CBufferDC::Detach() { return CDC::Detach(); }