삽질하는플머

'분류 전체보기'에 해당되는 글 130건

  1. 원격 커멘드 - rcmd 1
  2. 삽질하는플머 위키 - PHP-GD
  3. 삽질하는플머 위키 - XML-RPC 갖구놀기
  4. rsync 가지고 놀기 2
  5. 숫자를 한글로 바꾸기

원격 커멘드 - rcmd

탐구생활/Others
원격 컴퓨터의 콘솔 프로그램을 실행하고 그 결과를 내 컴퓨터에 뿌려줘야 한다면? 바로 떠오르는 해법은 SSHD 를 설치해 사용하는 것이다. 하지만 로컬 네트웍에서 간단한 작업을 위해 cygwin 깔고 SSHD 설정하고 키를 교환한다는 건... 왠지 소잡는 칼을 생선 다듬는 데 휘둘러대는 폼안나는 일이라 생각된다. 

해서 간단한 유틸리티를 만들어볼까 폼잡다가 윈도 2000 리소스킷에서 멋진 솔루션을 발견했다. 이름하여 rcmd / rcmdsvc !! 
오늘은 이 물건을 가지고 재미나게 놀아보자!! (검색 안해보고 만들었으면 속 좀 쓰릴 뻔...)

다운로드는 여기서 "Remote command service" 를 클릭하면 rcmd.zip 을 얻을 수 있다. 압축을 풀면 rcmd.exe 와 rcmdsvc.exe 가 나온다. 

(나중에 찾아가기 귀찮으니 걍 여기에 붙여두자)

1. rcmdsvc.exe 를 서비스로 등록. 

"Service Controller Query Tool" 이라 불리는 sc.exe 는 예전에는 리소스킷으로 제공되었었는데 XP에는 이미 포함되어있다. 
압축이 풀린 rcmd.exe 와 rcmdsvc.exe 를 윈도우의 System32 폴더로 옮기고 커맨드창에서 다음과 같이 입력하자. 

C:\>sc create rcmdsvc binPath= C:\WINDOWS\system32\Rcmdsvc.exe displayname= "Remote command service" start= auto

[SC] CreateService SUCCESS


제어판의 서비스 항목에 방금 설치한 Remote command service 가 제대로 들어갔는지 살펴보자. 




여기서 "시작" 버튼을 살포시 눌러주거나, net start rcmdsvc 또는 sc start rcmdsvc 로 서비스를 시작한다. 
(등록된 서비스를 삭제하는 명령은 sc delete rcmdsvc 이다.)


2. 로컬에서 테스트.

이제 준비된 서버에 접속해보자. rcmd.exe 를 과감하게 실행시킨다. 




서버의 이름을 입력하라는 안내가  나온다. 로컬 서버의 IP인 127.0.0.1 을 입력하면 서비스가 실행된 계정인 LocalService 의 홈디렉토리를 기준으로 셸이 열리게 된다. 

실행 후 서버의 CMD를 띄우는 방식 외에 다음과 같이 직접 명령어를 입력하고 결과를 받아올 수도 있다. 
(도메인 이름 앞에 역슬래시 두개가 붙는 것에 유의하자.)

C:\> rcmd \\127.0.0.1 dir c:\ /w


실행 결과는 다음과 같다. 




3. 원격지에서 접속.

로컬에서만 띄우면 이게 뭐지 싶을 것이다. 이제 원래 목적이었던 원격지에서의 접속을 테스트 해 보자. 
이 글에서 rcmdsvc 서비스를 동작시키는 컴퓨터의 내부 네트웍 IP 는 192.168.29.1 이다. 다른 컴퓨터에서 이 컴퓨터의 dir 명령을 내려보자. 

C:\> rcmd \\192.168.29.1 dir c:\ /w

Error - Failed to connect to <\\192.168.29.1>, Error = 1326


1326 에러는 대상 컴퓨터의 IPC 권한을 갖지 못했기 때문에 발생한다. 네트워크 공유 연결과 동일한 방식으로 권한을 획득해주자. 

C:\> set user=[사용자명]
C:\> set passwd=[비밀번호]]

C:\> net use \\192.168.29.1\IPC$ %PASSWD% /user:%USER%
명령을 잘 실행했습니다.


이제 앞에서 내렸던 rcmd 명령을 다시 실행하면 원격지의 C 드라이브 내용을 볼 수 있게 된다. 

확보한 IPC 권한은 다음과 같은 방법으로 반환할 수 있다. 

C:\>net use \\192.168.29.1\IPC$ /delete
\\192.168.29.1\IPC$이(가) 제거되었습니다.


콘솔창에서 입력이 아닌 델파이에서 대상지의 IPC 권한을 확보하는 방법은 예전에 델마당에 올렸던 강좌를 참고하자.


// 도메인에 연결을 만든다.
function UseConnection(const aDomain, aUserID, aPassWord: String; var ConnStr: String): Boolean;
var
  NetResource: TNetResource;
  ConnStrLen: DWORD;
  RetFlag: DWORD;
  RetValue: DWORD;
begin
  FillChar(NetResource, SizeOf(TNetResource), 0);

  with NetResource do
  begin
    dwType := RESOURCETYPE_ANY;
    lpLocalName := nil;   // 로컬 드라이브 지정하지 않음
    lpRemoteName := PChar('\\' + aDomain);
    lpProvider := nil;
  end;

  SetLength(ConnStr, MAX_PATH);
  ConnStrLen := MAX_PATH;
  RetValue:=
    WNetUseConnection(
      0, NetResource,
      PChar(aPassWord), PChar(aUserID), CONNECT_INTERACTIVE,
      PChar(ConnStr), ConnStrLen, RetFlag
    );
  SetLength(ConnStr, StrLen(PChar(ConnStr)));

  ConnStr := '\\'+aDomain;

  Result := RetValue = 0;
end;


var
  ConnStr: String;
...
  UseConnection('192.168.29.1\IPC$', 유저이름, 패스워드, ConnStr) 


이 호출이 True면 권한 확보가 된 상태이므로 rcmd 를 사용할 수 있게 된다. 다 사용한 권한은 WNetCancelConnection() API 로 반환한다. 

WNetCancelConnection(PChar(ConnStr), true)


응용범위는 사실 무궁무진한데... 예를 들어 여러대의 PC에서 메인 PC의 스케줄에 따라 rsync 로 동기화해야 할 경우도 이 방법을 사용하면 중앙의 한 대의 PC에서 간단히 해결할 수 있다. 또한 Screen 과 버무리면 지금 서비스중인 게임에서 SSH 를 걷어내고 설정을 간단히하는 용도로 사용할 수도 있을 것이다. 

쓰기 편한 방법은 항상 보안위험에 노출되어있다. 하지만 SSHD 를 띄우고 키를 교환해두는 것도 불편함을 해결하기 위해 보안은 나몰라라 하는 것은 마찬가지이고, 또한 IPC가 로컬네트웍에서만 유효하다는 것을 감안하면 생선 비늘 벗기는 용도로는 딱 알맞은 칼이라 생각된다. 




한가지 http://www.simpleisbest.net/archive/2005/10/18/260.aspx 이 사이트의 내용을 보면 "HKEY_CURRENT_USER 레지스트리에 접근하면 데스크탑에 로그온한 사용자의 레지스트리가 아닌 로컬 서비스 계정의 레지스트리가 액세스되어 버릴 것이다" 라는 무시무시한 구절이 있다. 흠.. 이건 좀 곤란한데... 진짜로 그런지 확인해보자. 

일단 로컬시스템에서 적당한 레지스트리를 익스포트 하자. (뭐하는데 쓰는지는 잘 모르겠지만 값이 달랑 하나라 선택)

regedit /E "C:\test.reg" HKEY_CURRENT_USER\Calendar


출력된 C:\test.reg 파일의 내용은 다음과 같다. 

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Calendar]
"Skin"="1"


이제 이 Skin 값을 뭐 한 100 으로 바꿔준 뒤, 원격지에서 임포트 할 때 제대로 들어가는지 확인해 보자.

rcmd \\192.168.29.1 regedit /S C:\test.reg


로컬로 돌아와 레지스트리 편집기를 열어서 확인해본다. 




흠... 제대로 잘 들어가는뎅... 





당연한 얘기지만 서비스를 Interactive Service 로 설정하지 않으면, 즉 데스크탑과 상호연동을 시키지 않으면 윈도를 띄우거나 하는 일은 불가능. 즉 rcmd 로 원격지의 "윈도 어플" 을 실행시키면 이 윈도는 LocalService 계정에서 실행되고 나타나지 않는다.  

심심해서 rcmdsvc 의 로그온 설정의 "서비스와 데스크톱 상호 작용 허용" 을 체크하고 재구동한 뒤 원격지에서 로컬컴퓨터의 맵서버를 구동시켜 봄. 원격지에서 조작윈도나 루아윈도를 띄우는 명령을 내리면 이 창은 모두 로컬에서 나타난다.




오래전 GPG 글에서 rcmd 관련된 언급을 발견하고 반가워서 트랙백을 걸어둠. 


삽질하는플머 위키 - PHP-GD

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

삽질하는플머 위키 - XML-RPC 갖구놀기

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

rsync 가지고 놀기

탐구생활/CYGWIN
rsync 는 로컬, 또는 리모트의 파일들을 동기화하는 멋진 물건이다. 
미루어두었던 cygwin 상에서 rsync 삽질내용을 정리하자. 

한동안 cygwin 을 돌리지 않았더니 버전이 2.697 -> 2.721 로 올라가버림. 업데이트에 한세월이 걸리네...

rsync는 rsync --daemon 옵션을 통해 데몬으로 동작시킬 수 있다. 

rsync --daemon --configure=rsyncd.conf

rsyncd.conf 에 지정된 PID파일에는 rync 데몬의 PID가 기록된다. 종료시에는 이 값을 참고하면 된다.  

매번 이 작업이 싫다면 cygrunsvc 를 이용해 서비스로 등록하면 될 듯. 
고맙게도 rsync를 이용한 백업방법을 깔끔하게 정리해둔 곳이 있다. 소스포지에 적절한 구성예제도 있고 말이지...


이걸 함 따라해보자. 

먼저 소스포지에서 cygwin-rsyncd-2.6.8_0.zip 을 내려받아 압축을 푼다. 이 파일은 cygwin 에서 rsync 데몬구동에 필요한 요소만 추려낸 것이다. (나중에 sshd 구성요소를 독립시켜 쓰는데도 많은 참고가 될 듯 하다.) 
압축이 풀린 파일들 중 다음 파일들을 C:\cygwin\etc\rsyncd-conf 에 옮긴다. 

  • rsyncd.conf
    rsyncd.secrets
    Rreadme.txt - 별 필요없지만... 

rsyncd.secrets 파일을 열고 적절한 사용자명과 패스워드를 설정한다. 여기서는 oranke:1234 마지막 한 줄은 비워야 한다. 

# Also: make sure this file ends in a newline.  Otherwise the last
# username/password pair will be ignored.
#
UUU:PPP
oranke:1234


rsyncd.conf 파일을 열고 경로명을 제대로 맞춰준다. 

# Uncomment this line and change the path if
# you would like to log rsync messages.
#
# log file = c:/cygwin/etc/rsyncd-conf/rsyncd.log

#
# The location of the rsync process ID file
#
# 서비스 구동시 재부팅하면 pid 파일이 남아있게 된다. 
# pid 파일이 있으면 데몬이 실행되지 않으므로 이 부분도 주석처리 한다. 
# pid file = c:/cygwin/etc/rsyncd-conf/rsyncd.pid

#
# The locations of the rsync lock file
#
lock file = c:/cygwin/etc/rsyncd-conf/rsyncd.lock


auth users 섹션을 찾아  secrets 에 추가한 아이디를 지정해준다. 

auth users = UUU, oranke


secrets file 역시 수정된 경로로 맞추어준다. 

    secrets file = c:/cygwin/etc/rsyncd-conf/rsyncd.secrets


이 곳에 접속할 rsync 클라이언트의 아이피를 제한하려면  hosts allow 섹션의 주석을 털어주고 적절한 아이피를 설정한다.  

    # hosts allow = 172.16.0.17


기본적으로 이 설정파일은 'C:\Documents and Settings' 폴더를  백업하는 방식이다. 여기서는 테스트를 위해 이 설정을 'C:\SyncWork-Test' 로 변경한다. (여기까지 작업된 파일은 백업하고 수정하는 편이 좋겠군.) 
주의 ! 여기서 path 값은 cygpath 로 지정해야 한다. 

[SyncWork-Test]
    # path = c:/SyncWork-Test
    path = /cygdrive/c/SyncWork-Test
    comment = Sync work test
    strict modes = false
    auth users = UUU, oranke
    secrets file = c:/cygwin/etc/rsyncd-conf/rsyncd.secrets
    # hosts allow = 172.16.0.17
    # 서버로 파일전송이 가능하게 하려면 read only = false 로 할 것. 
    # 현재는 가져가는 용도로 설정하고 있으므로 true 로 되어있음. 
    read only = true
    list = false


rsyncd.secrets 파일의 속성을 '읽기 전용' 으로 변경한다. 우클릭 후 읽기전용 체크로 간단히 해결.
또는 이렇게 
chmod 600 rsyncd.secrets 


이제 대강 준비는 완료. 남은 것은 rsyncd 를 서비스로 동작시켜야 한다. cygrunsrv 를 쓰면 되는데... 아까 받아둔 zip 에 예제가 있다. 

cygrunsrv.exe -I rsyncd -e CYGWIN=nontsec -p c:/cygwin/bin/rsync.exe -a "--config=c:/cygwin/etc/rsyncd-conf/rsyncd.conf --daemon --no-detach"


예전 sshd 처럼 서비스 표시이름이 CYGWIN rsyncd 로 보이게 하려면 -d 또는 --disp 옵션을 추가한다. 

cygrunsrv.exe -I rsyncd -d "CYGWIN rsyncd" -e CYGWIN=nontsec -p c:/cygwin/bin/rsync.exe -a "--config=c:/cygwin/etc/rsyncd-conf/rsyncd.conf --daemon --no-detach"


경로명을 cygpath 로 쓰라는 경고가 나오긴 하지만 무시해도 괜찮음. 신경쓰인다면 -p 옵션 뒤의 rsync.exe 경로를 /bin/rsync.exe 로 바꿔줄 것. 

시작 -> 실행 에서 services.msc 를 입력 후 "CYGWIN  rsyncd" 가 제대로 표시된다면 제대로 따라온 것임. 



마지막으로 방화벽에서 ryncd 가 사용할 873번 포트를 열어주자. 

  • Name: rsyncd
    Port number: 873
    Type: TCP




또는 cygwin-rsyncd-2.6.8_0.zip 내의 배치파일에 쓰인 netsh 명령어를 사용할 수 있다. 

netsh firewall set portopening protocol = TCP port = 873 name = rsyncd mode = enable scope = CUSTOM addresses = LocalSubnet


모든 준비가 끝났으면 다음 명령어로 이 rsyncd 서비스를 시작해본다.  

cygrunsrv --start rsyncd
    또는
 net start rsyncd 


telnet localhost 873 명령을 내려보면 rsyncd 가 제대로 동작하는지 확인할 수 있다. 또한 c:\cygwin\etc\rsyncd-conf 폴더에는 rsyncd.pid 파일이 생성되며 이 파일의 내용을 열어보면 ps -eaf | grep rsync 로 출력되는 rsyncd 의 PID와 일치한다. 앞에서도 언급했듯이 데몬 종료는 이 프로세스를 Kill로 죽이면 되지만... 지금은 서비스로 구동시키고 있으므로 참고만 하자. 




이제 rsyncd 의 파일을 임의 폴더에 동기화시켜보자. 
아까 설정해 둔 'C:\SyncWork-Test' 폴더에 적당한 파일들을 넣어둔다. 
그리고 임의 폴더로 이동한 뒤 다음과 같은 명령어를 내려보자. (-a 는 아카이브, -v 는 목록표시 옵션이다.)

$ rsync -av oranke@localhost::SyncWork-Test
Password:
receiving incremental file list
drwx------           0 2010/10/27 16:37:10 .
-rwx------      863778 2010/10/27 16:12:22 aaa.bmp
-rwx------        7037 2010/10/27 16:12:26 aaa.png
-rwx------        2884 2005/11/25 02:54:51 curl_stack.h
-rwx------      196360 2006/06/22 21:40:25 curl_stack.o
-rwx------        5112 2006/06/22 21:39:25 main.cc
-rwx------      443728 2006/06/22 21:40:27 main.o

sent 65 bytes  received 203 bytes  107.20 bytes/sec
total size is 1518899  speedup is 5667.53



싱크를 위해 올려둔 파일의 목록이 잘 출력되는 것을 볼 수 있다. 
뒷부분에 받을 경로를 지정함으로서 실제로 파일을 전송받을 수 있다. 다음과 같이 명령어를 바꿔보자. 

$ rsync -avz --delete oranke@localhost::SyncWork-Test ./
Password:
receiving incremental file list
./
aaa.bmp
aaa.png
curl_stack.h
curl_stack.o
main.cc
main.o

sent 182 bytes  received 153356 bytes  43868.00 bytes/sec
total size is 1518899  speedup is 9.89


잘 전송된다. 처음 실행했을 때와 옵션을 조금 바꾸어주었는데, -z 는 전송시 정보를 압축, --delete 는 서버에서 지워진 파일을 여기서도 지우라는 옵션이다. 제대로 잘 지워지는지 C:\SyncWork-Test 폴더에서 임의의 파일을 삭제하고 다시 저 명령을 내려보자. 

$ rsync -avz --delete oranke@localhost::SyncWork-Test ./
Password:
receiving incremental file list
deleting main.cc
./

sent 68 bytes  received 194 bytes  104.80 bytes/sec
total size is 1513787  speedup is 5777.81


일단 이정도의 기능만으로도 충분히 증분백업 환경 구축이 가능할 듯 싶은데... 나머지는 차차 뒤져보자구.



* rsyncd.conf 의 auth users, secrets files 항목을 주석처리하면 암호입력 없이 접근할 수 있다. 

rsync -avz --delete localhost::SyncWork-Test ./

또한 접속시 콜론을 한개만 사용하면, 접속에 rsh 를 사용하게 된다. 

rsync -avz --delete localhost:SyncWork-Test
oranke_f@localhost's password:
receiving incremental file list
rsync: link_stat "/home/oranke_f/SyncWork-Test" failed: No such file or directory (2)

sent 8 bytes  received 12 bytes  3.08 bytes/sec
total size is 0  speedup is 0.00
rsync error: some files/attrs were not transferred (see previous errors) (code 23) at /home/lapo/packaging/rsync-3.0.7-1/src/rsync-3.0.7/main.c(1508) [Receiver=3.0.7]

에러난 화면이지만 자세히보면 rsync 는 localhost 의 oranke_f 계정의 SyncWork-Test 디렉토리를 찾게 된다. oranke_f 가 지정된 것은 현재 작업중인 세션의 로그온 유저이기 때문이다. 따라서 다음과 같은 방식으로

$ rsync -avz --delete user@localhost:Some-Dir ./

특정 유저의 디렉토리를 동기화 할 수도 있다. (SomeDir 에 ./ 를 넣어봐도 재밌다.)

역으로 이런 처리도 가능. 

$ rsync -avz ./ oranke_f@localhost:test
oranke_f@localhost's password:
sending incremental file list
./
1232612189_IMG_0861.jpg
1271342789_QUvpyA8N_EAB7B8EB94B4EAB1B4.jpg
1282266251_fVObgSNQ_bman.png
200308187.jpg
20060912k_2.gif
83221693.jpg

sent 1788868 bytes  received 129 bytes  511142.00 bytes/sec
total size is 1787778  speedup is 1.00


localhost 의 oranke_f 홈의 test 디렉토리로 현재 디렉토리의 파일을 전송하는 예이다. 

단순히 rsyncd 데몬만 띄운 상태로 rsh 가 결합되니 참 유용해지는군. ssh를 쓰고 키교환을 미리 해두면 말 그대로 끝내주겠는걸~~
(잘 이해가 안되는건... 현재 테스트중인 PC에 rsh 데몬따위는 없는데... ssh가 기본으로 돌아버리는데... 신기함... )

중간에 몇가지 주의해야 할 부분이 있기는 하지만 ssh를 사용하는 참고자료. -e ssh 옵션이 눈에 띈다. 




rsyncd 가 사용하는 포트변경은 리눅스의 경우 xinetd 에서 할 수 있다. 

cygwin 은 잘 모르겠네... 
아무튼 변경된 포트로 접속할 때는 --port 옵션을 사용한다. 

rsync --port=NNN ....


찾아봐도 없어서 도움을 구합니다...
-e ssh -p 5000 .. 이런 씩으로 하면 작동이 안돼네요

==> rsync으로 백업하고자 할경우에 ssh보안 프로토콜의 사용자 정의 포트 (예: 5000)로
연결하여 백업하고 자 할경우 아래와 같이 --rsh 옵션을 활용하시기 바랍니다.

#> rsync -av --progress --inplace --rsh='ssh -p5000' somefile user@host:somedir/  [엔터]





rsync 를 이용하여 윈도우즈 백업하기 Mini-HOWTO  


시간날 때 cygwin 에서 rsync, sshd 에 필요한 요소만 추려서 설치할 수 있는 방법도 고민해보자. 

윈도에서 쓰기 좋게 패키징된 물건
http://sourceforge.net/projects/backuppc/files/cygwin-rsyncd/
http://backuppc.sourceforge.net/


숫자를 한글로 바꾸기

탐구생활/Delphi

간단할 것 같았는데 만단위 절삭, "일"을 표시하거나 말아야 하는 경우 등  생각해야 할 부분이 꽤 많다. 
사실 델마당 강좌란에 이미 병규형님이 만들어두신 숫자 -> 한글 함수가 있지만, "일"을 생략해야 하는 경우의 처리가 없어서 이번 기회에 잘 버무려놓기로 한다. 

문제는 귀차니즘... 잠시 고민하다 최종욱님 블로그에서 자바로 된 코드를 걷어다 델파이로 바꾸어보았다. 



(*
  임의의 숫자를 받아 한국어 숫자 표기 기법에 따라 변환한 문자열을 반환

  최종욱님의 자바코드를 델파이로 변환.
  http://link.egloos.com/4165494

  파라미터
    Number    : 한국어로 바꿀 숫자
    DecimalSp : 만단위 단위로 공백 삽입 여부. 
    Official  : 이 값이 True 면 '일'을 생략하지 않는다.
*)

function IntToKorean(Number: Int64;
  DecimalSp: Boolean = false;
  Official: Boolean = false): String;
const
  NumberStr : Array [0..7] of String = (
    '이', '삼', '사', '오', '육', '칠', '팔', '구'
  );
  LevelStr : Array [0..2] of String = (
    '십', '백', '천'
  );
  DecimalStr : Array [0..4] of String = (
    '만', '억', '조', '경', '해'
  );

var
  Digits: String;
  Len: Integer;
  SubCount: Boolean;

  Base: Integer;     // 현재 다루고 있는 자릿수. 
  BaseMod4: Integer; // 만단위내 일십백천 단위.
  Digit: Integer;

  i: Integer; 
begin
  if Number = 0 then
    Result := '영'
  else
  if (Number < 0) then
    Result := '마이너스 ' + IntToKorean(-Number, Official)
  else
  begin
    Digits := IntToStr(Number);
    Len := Length(Digits);
    SubCount := false;

    for i:= 0 to Len-1 do
    begin
      Base := Len -i -1;
      BaseMod4 := Base mod 4;
      Digit := Ord(Digits[i+1]) - Ord('0');

      if Digit <> 0 then
      begin
        SubCount := true;

        if Digit = 1 then
        begin
          if Official or (BaseMod4 = 0) then
            Result := Result + '일';
        end else
          Result := Result + NumberStr[Digit-2];

        if BaseMod4 > 0 then
          Result := Result + LevelStr[BaseMod4-1];
      end;


      if BaseMod4 = 0 then
      begin
        if SubCount and (Base > 0) then
        begin
          Result := Result + DecimalStr[Base div 4 - 1];

          if DecimalSp then
            Result := Result + ' ';
        end;
      end;
    end;
  end;
end;


숫자값 123523121821 을 변환할 경우 

IntToKorean(123523121821);
  결과 : 천이백삼십오억이천삼백십이만천팔백이십일

IntToKorean(123523121821, true);
  결과 : 천이백삼십오억 이천삼백십이만 천팔백이십일

IntToKorean(123523121821, true, true);
  결과 : 일천이백삼십오억 이천삼백일십이만 일천팔백이십일