생각하는 족족 고.따.구 냐..

Posted
Filed under About Knowledge/OS_Unix

EMACS도 사용하기 시작합니다.

메일로 보낼 수 있다기에, 메일을 보내 봣습니다.

되는 것 처럼 보였습니다. 그래서 남깁니다. 또 써먹으려...

아래 글의 출처는 "http://kldp.org/node/84427"  입니다.

===================================================================

지메일의 받고 보내는 서버는 다음과 같다.

서버 종류 설정
받는 메일 서버 (POP3) pop.gmail.com

SSL: 사용함

포트: 995
보내는 메일 서버 (SMTP) smtp.gmail.com (인증 사용)

STARTTLS: 사용함

포트: 465와 587

이것은 지메일에서 POP 신청을 한 후에 이용 가능하다. 만약 이미 지메일을
다른 메일 클라이언트에서 이용하고 있다면 이미 신청을 한 것이다. 그렇지
않다면 지메일 설정에 가서 POP 신청을 하면 된다. 신청을 하면 POP3 뿐만
아니라 SMTP까지 이용할 수 있다.

그렇다면 지메일의 SMTP를 이용하는 방법을 알아보자. 시작 스크립트에
등록하는 방법을 이용할 수도 있고, Customize를 이용하는 방법이 있는데,
Customize를 이용하는 방법을 알아보자.

  1. M-x customize-group RET mail RET을 한다.
  2. 사용자 이름 등 필요한 설정을 하고 C-x C-s를 하여 설정을 저장한다.
  3. M-x customize-variable RET send-mail-function RET을 한 뒤
    smtpmail-send-it으로 설정한다. 이것을 하지 않으면 sendmail
    프로그램을 통하여 메일이 전송된다. C-x C-s로 저장한다.
  4. M-x custoimze-variable RET message-send-mail-function RET을 한 뒤
    message-smtpmail-send-it을 설정한다. C-x C-s로 저장한다.
  5. ~/.signature 파일에 자신의 메일 서명을 쓰고 저장한다.
  6. M-x customize-group RET smtpmail RET를 한다.
  7. smtpmail-default-smtp-server와 smtpmail-smtp-server를
    smtp.gmail.com 으로 설정한다.
  8. smtpmail-smtp-service를 587로 설정한다.
  9. smtpmail-starttls-credentials에서 State를 누르고 :키를 눌러 LISP
    형태로 나타나게 한다. 이렇게 하는 이유는 nil을 입력할 수 있는
    방법이 없게 되어 있는 문제점이 있기 때문이다.
  10. 빈 칸에 '(("smtp.gmail.com" 587 nil nil))를 입력한다.
  11. smtpmail-auth-credentials에 Value Menu를 누르고 Repeat를 선택한다.
  12. INS 버튼을 누른 다음에 필요한 내용을 집어 넣는다. 여기서 사용자
    이름에는 반드시 @gmail.com까지 포함시켜 완전한 이메일 주소를
    넣어야 한다.
  13. 패스워드는 넣지 않으면 보낼 때마다 물어본다.
  14. C-x C-s를 눌러 설정 파일을 저장한다.

만일 패스워드를 매번 입력하는 것이 귀찮지만 이맥스 설정 파일에
패스워드를 집어넣는 것이 마음 편하지 않다면 따로 netrc 형태의 파일을
만들고 거기에 집어넣고 permission을 변경하는 방법이 있다.

임의의 파일을 하나 생성하여 퍼미션을 600으로 준 뒤 다음과 같이 입력하고
저장하고 M-x customize-variable RET smtp-auth-credentials RET를 하고
Value Menu를 눌러 파일 형태를 선택하고 그 파일 이름을 입력하면 된다.

machine smtp.gmail.com login username@gmail.com password PASSWORD

이제 C-x m을 눌러 메일을 작성한 뒤 C-c C-c를 눌러서 메일을 전송하면
된다. 먼저 자기 자신에게 테스트 메일을 보내본다. 언어 설정 등이 제대로
되어 있다면 한글로 보낸 경우에도 깨지지 않고 메일이 잘 전송될 것이다.

VM을 이용하는 사람들은 Bill Clementson's Blog: VM and Gmail Setup for
Dummies
를 참고한다.

Blog entry: http://turtleforward.blogspot.com/2007/07/smtp.html

이 글을 공유하기:
2011/07/23 17:37 2011/07/23 17:37
Posted
Filed under About Knowledge/OS_Unix
Back Quotes ( ` )  not '


command substitution



In computing, command substitution is a facility originally introduced in the Unix shells that allows a command to be run and its output to be pasted back on the command line as arguments to another command. Shells typically do this by creating a child process to run the first command with its standard output piped back to the shell, which reads that output, parsing it into words separated by whitespace. Because the shell can't know it has all the output from the child until the pipe closes or the child dies, it waits until then before it starts another child process to run the second command.
2010/11/09 17:33 2010/11/09 17:33
Posted
Filed under About Knowledge/OS_Unix
Document Audience: SPECTRUM
Document ID: 72293
Title: How to Mount or Unmount a USB Mass Storage Device without VOLD running.
Update Date: Fri Jan 21 00:00:00 MST 2005
Products: Desktops & Workstations, Solaris
Technical Areas: USB (Universal Serial Bus) Port ===========================================================

Keyword(s):usb, mount, umount, vold, mass storage

Description: Top

 This document describes the procedure to mount and unmount filesystems on USB Mass Storage devices without the Volume Management daemon (vold) running.

Document Body: Top

Before doing this, be sure the lastest Recommended Patches for Solaris have been updated. See the mount(1M) man page for more details on the 'mount' and 'umount' commands.

 If the disk is unformatted and creating a filesystem is necessary, see Document ID 76911.

==================================
Mounting a USB Mass Storage device
==================================

1. Identify the symbolic link in the '/dev/dsk/' directory for the device you want to mount.

Optional : You may have stale '/dev/' links that could become cumbersome and misleading to work with. To clean this up, use the Cleanup mode of the devfsadm(1M) command :

# devfsadm -C

Symbolic links for USB devices are found in the '/dev/usb/' directory. The USB Mass Storage devices appear as 'mass-storageX', where "X" is an index number.

# ls -l /dev/usb/mass-storage*
lrwxrwxrwx 1 root root 53 Aug 10 16:06 /dev/usb/mass-storage0 -> ../../devices/pci@8,700000/usb@5,3/ storage@1:scsa2usb

 For these same devices, symbolic links are also created in the '/dev/dsk/' and /dev/rdsk/' directories.

# ls -l /dev/dsk/*s2 | grep usb
lrwxrwxrwx 1 root root 55 Aug 10 16:06 /dev/dsk/c3t0d0s2 -> ../../devices/pci@8,700000/usb@5,3/storage@1/disk@0,0:c

In the above example, notice the device path (/devices/pci@8,700000/usb@5,3/storage@1) matches for the symbolic links /dev/usb/mass-storage0 and /dev/dsk/c3t0d0s2.

2. Become SuperUser.

3. Mount the USB Mass Storage device filesystem.

Here is the basic command :

# mount -F /dev/dsk/

Where "X" is the appropriate values for your device (See step 1).

Here are some examples of mounting various devices.

  A. For a read-only CD-ROM filesystem (hsfs) :

    # mount -F hsfs -o -ro /dev/dsk/c1t0d0s2 /mnt

  B. For devices with pcfs (FAT) filesystems (Zip, Jaz, Flash or "key"-style) :

    # mount -F pcfs /dev/dsk/c3t0d0s2:c /mnt

4. Verify the filesystem is mounted.

  A. Use the mount(1M) command Example :

    # mount | grep /mnt
 
  B. Use the cd(1) and/or ls(1) commands

    Example :

    # cd /mnt
    # ls /mnt

  C. Use the df(1M) and/or du(1) commands

    Example :

    # df /mnt # du /mnt

====================================
Unmounting a USB Mass Storage Device
====================================

1. Become SuperUser.

2. Unmount the USB mass storage device.
 
Here is the basic command :

  # umount

  Example :

  # umount /mnt
2010/10/05 09:27 2010/10/05 09:27
Posted
Filed under About Knowledge/OS_Unix

임베디드 리눅스 소프트웨어 개발의 빌드 환경 구축을 위한 글을 찾았습니다.

[http://wildduck.tistory.com/77] 을 글을 참조 합니다.

======================================

Technical Report

임베디드 리눅스 S/W 개발 생산성 향상을 위한 원격 빌드 환경 구축

                                                                                          2009. 12. 02 오화종

1.     들어가며

임베디드 리눅스 S/W 개발 환경은 일반적인 S/W 개발 환경에 비해 많은 제약을 갖는다. 특히,  타켓 장비와 개발 장비가 달라 크로스 컴파일러를 사용해야 하며, 개발 장비의 운영체제를 리눅스가 아닌 윈도우즈를 사용하면 소스 코드 에디팅은 윈도우에서 하고 컴파일은 리눅스 머신 또는 가상 리눅스 머신에서 해야 하는 불편함이 있다. 본 글에서는 오픈소스 IDE Eclipse와 리눅스의 Samba, SSH를 연동하여 마치 하나의 개발 장비에서 소스 코드 에디팅과 컴파일을 하고 컴파일 워닝 또는 오류 메시지를 IDE 상에서 비주얼하게 확인하는 방법을 소개한다. 이 원격빌드 환경을 구축하여 S/W를 개발하면 소스 코드 에디팅 결과를 빠르게 확인하고 처리할 수 있게 되어 전체적으로 개발되는 S/W의 품질 및 개발 생산성을 향상 시킬 수 있을 것이라 생각한다. 여기에 덧붙여 구축된 환경에서 이용 가능한 유용한 기능들을 간략히 소개한다.

 

2.     원격 빌드 환경 구축

최종 구성된 원격 빌드 환경은 그림 1 과 같이 크로스 컴파일러가 설치된 리눅스 빌드 서버와 Eclipse IDE를 실행하는 개발 PC, 타겟 단말기로 구성되며, 원격 에디팅 및 컴파일을 위하여 Samba SSH를 사용한다. 빌드서버의 경우 개발 PC와 분리된 리눅스 서버 또는 개발 PC에서 동작하는 가상 리눅스 서버가 사용될 수 있다. 최종 빌드된 바이너리는 ftp를 통하여 빌드서버에서 개발단말기로 전송되거나 serial 라인을 통하여 전송될 수 있다.


사용자 삽입 이미지


n  Eclipse CDT - C언어용 오픈소스 IDE. http://www.eclipse.org 참조

n  Samba - 리눅스 파일 시스템을 공유를 위한 유틸리티

n  SSH - Secure Shell. 암호화된 패킷을 송수신하는 안전성이 향상된 Telnet 버전

개발 PC에서는 빌드서버에서 Samba로 오픈한 디렉토리를 윈도우즈의 네트워크 드라이브로 잡은 후 그곳에 Eclipse CDT의 프로젝트를 생성하여 소스코드를 편집한다. 원격 빌드는 Eclipse CDT Make Target 실행시 SSH 원격 커맨드 실행을 수행하게 하여 빌드서버의 크로스 컴파일러를 실행시키고 그 결과를 받아와 IDE 화면에 표시하게 된다. 자세한 설정 과정은 아래와 같으며 본인이 사용하고 있는 Vmware Ubuntu 리눅스(가상 IP: 192.168.222.160)를 빌드서버로 하는 환경을 예로 설명한다.

    리눅스의 Samba 설정

리눅스 서버에 Samba를 설치하고 설정파일 /etc/samba/smb.conf 을 그림 2 와 같이 수정한 후 /etc/init.d/smb restart 명령으로 Samba를 재구동하여 사용할 디렉토리를 오픈한다. 예제 에서는 편의상 전체 파일시스템을 오픈하였다.

사용자 삽입 이미지

그림 2

    윈도우즈의 네트워크 드라이브 설정

위에서 공유된 리눅스 파일 시스템을 윈도우즈에서 네컴퓨터 à 도구 à 네트워크 드라이브 연결을 선택하여 네트워크 드라이브로 잡는다. 예제 에서는 Z 드라이브, \\192.168.222.130\root  를 네트워크 드라이브로 잡았다. 이렇게 하면 윈도우에서 리눅스 파일시스템을 마치 로컬디스크 처럼 사용할 수 있게 된다.

    SSH 설정

리눅스 서버에 SSH를 설치한 후 개발PC 사용자의 공개키를 저장한다. 이것은 원격 빌드를 위하여 개발 PC Eclipse CDT 에서 SSH를 사용하는데 매번 아이디/패스워드를 입력하지 않게 하기 위함이다.

n  공개키 생성

그림 3 과 같이 cygwin ssh-keygen 명령으로 공개키를 생성한다. (cygwin openssh 패키지)

공개키는 /home/administrator/.ssh/id_dsa.pub 파일로 생성되었다.

사용자 삽입 이미지


그림 3

n  빌드서버에 공개키 복사 및 인증키 목록 갱신

위에서 생성된 공개키 파일을 빌드서버의 /root/.ssh 폴더에 복사한 후 인증키 목록 추가를 위해 그림 4 와 같이 ssh-copy-id 명령을 실행한다. 여기서 root@192.168.222.130 부분은 ‘접속계정@호스트이름 형식이다.

사용자 삽입 이미지


그림 4

     Eclipse CDT 프로젝트 설정

n  프로젝트 생성

Eclipse를 실행시킨 후 그림 5 와 같이 메뉴 à 파일 à NEW à C Project 를 선택하여 프로젝트를 생성한다. 이때 생성 위치는 네트워크 드라이버로 잡은 빌드서버의 디렉토리로 한다.

사용자 삽입 이미지

그림 5

n  시스템 함수 검색을 위한 시스템 헤더파일 위치 설정

메뉴 à Project à C/C++ General à Paths and Symbols 를 선택하여 그림 6 과 같이 리눅스 빌드서버에 설치 되어 있는 크로스 컴파일러가 사용하는 시스템 헤더파일 위치를 설정한다.

사용자 삽입 이미지

그림 6

n  테스트 프로그램 작성

개발할 프로그램을 작성한다. 예제 에서는 그림 7 과 같이 간단한 프로그램을 작성하였다.

사용자 삽입 이미지

그림 7

n  Makefile 파일 작성

작성된 프로그램을 빌드하기 위한 Makefile을 그림 8 과 같이 만든다. 컴파일 옵션으로 -W -Wall 을 주어 최대한 컴파일러 워닝 레벨을 높인다.

사용자 삽입 이미지

그림 8

     Eclipse CDT Make Target 설정

SSH 원격 커맨드를 실행 하기 위하여 아래와 같이 Make Targets 창에서 all 타겟을 설정 한다.  그림 9 와 같이 메뉴 à 윈도우 à Show View 를 선택하여 Make Target 창을 뛰운 후 새로운 타겟을 설정한다. 이때 Build Command 항목에 SSH 원격 커맨드 실행 명령을 넣는다. 만약 시스템간의 locale 설정이 문제된다면 해당하는 locale이 반영 되도록 설정한다. 예제에서는 다음과 같이 설정 하였다.

ssh root@192.168.222.130 'export LANG=C; make -C /workspace/RemoteBuildTest'

사용자 삽입 이미지

그림 9

     원격 빌드 시연

n  원격 빌드

이제 모든 준비가 완료 되었다. 설정된 Make Targets 아이콘인 all을 더블클릭 하면 프로그램이 컴파일 되어 바이너리 파일이 아래와 같이 생성된다. 컴파일된 바이너리는 개발 PC가 아닌 리눅스 빌드서버에 생성된다. Eclipse CDT 에는 기본적으로 elf 바이너리 파서가 있어 빌드된 바이너리 이미지를 그림 10 과 같이 쉽게 분석할 수 있다.

사용자 삽입 이미지

그림 10

n  컴파일 워닝 및 오류 메시지 확인

그림 11 은 워닝 및 오류 메시지 확인을 위하여 소스수정후 원격 빌드한 결과이다. 해당 메세지가 IDE 화면에 비주얼하게 표시되는 것을 볼수 있다. 오류와 워닝 메시지가 구별되어 표시되며 쉽게 위치를 확인 할 수 있다.

사용자 삽입 이미지


그림 11

3.     Eclipse에서 사용 가능한 유용한 기능

위와 같이 Eclipse CDT 로 원격 빌드환경을 구축하면 추가적으로 Eclipse 및 연동 툴이 제공하는 유용한 기능들을 이용할 수 있다. 주요한 기능은 아래와 같다. 또한, Eclipse CDT 오픈소스 프로젝트는 국제적인 Eclipse 제단의 관리하에 매년 정규 릴리즈를 하고 있어 앞으로도 유용한 기능들이 빠르게 추가 보완 될 것으로 예상된다.

n  CVS SVN 연동

n  강력한 소스 브라우징

n  자동 리팩토링

n  자동 인덴테이션

n  원격 디버깅

n  버그 및 테스크 관리

위와 같은 여러 기능 및 도구들을 이용하면 일반 PC의 어플리케이션을 개발하는 것과 버금가는 편리한 환경을 구축 할 수 있다. 필자가 제안하는 임베디드 리눅스 S/W 개발용 통합 개발환경의 구성도는 그림 12 와 같다. 여러가지 다소 지루한 작업들을 자동화 시켜 프로그램 개발에 집중할 수 있고 이에 따라 개발 생산성 및 품질을 향상 시킬수 있을 것이라 생각한다.

사용자 삽입 이미지


그림 12

4.     마무리

임베디드 리눅스 S/W 개발 환경은 일반적인 개발 환경에 비하여 많은 제약이 있다. 하지만 최근 Eclipse 등의 유용한 개발 도구들이 임베디드 환경에서도 사용될 수 있도록 꾸준히 진화하고 있다. 이러한 툴들을 적절히 연동하여 사용하면 좀더 편리하고 자동화된 환경을 갖추어 S/W 개발 생산성 및 품질 향상에 도움이 될 것이라 생각한다. 본 보고서에서는 그중에 한가지인 원격빌드 환경을 구축하는 방법을 소개 하였다. 최근 급격하게 진화하고 있는 이러한 도구 및 기술들을 받아들이고 적절히 적용 시키는 것도 임베디드 S/W 개발에 중요한 요소가 아닐까 생각한다.

2010/10/01 00:17 2010/10/01 00:17
Posted
Filed under About Knowledge/OS_Unix
쉘 설정파일을 읽어들임

  • 쉘 설정파일을 읽어들여 적용
  • csh,tcsh,bash 의 내부 커맨드


얼라이어스나 변수등의 설정파일을 변경후 재로그인하지않고 바로 반영시킬때 사용.


[root@myspace ~]# source .bash_profile
2010/09/30 11:34 2010/09/30 11:34
Posted
Filed under About Knowledge/OS_Unix
1. X Window 원격 접속할 수 있는 프로그램

- VNC ( http://www.realvnc.com )
- Xmanager ( http://www.netsarang.co.kr )
- cygwin ( http://www.cygwin.com/ )
- eXceed
...

2. Remote Sessions via XDMCP

Cygwin/X can be used login to one or several remote sessions using XDMCP (X Display Manager Control Protocol).

Start Cygwin/X with a command similar to the following to login to a single remote session using XDMCP:

XWin.exe -query remote_hostname_or_ip_address

You may login to several remote sesstions with a single or multiple hosts using XDMCP. Each session will need a seperate display number, specified by the :display_number parameter, such as :0. A display number is not the same as a screen number, as a single display can have multiple screens associated with it. Each display listens on a different network port number, so each display can connect to multiple machines. Start Cygwin/X with command lines similar to the following to login to several remote sessions using XDMCP:

XWin.exe :0 -query remote_hostname_or_ip_address_0

XWin.exe :1 -query remote_hostname_or_ip_address_1

Note that the :display_number parameter is a general X Server parameter, not specific to Cygwin/X. Further documentation of the :display_number parameter can be found in the X Server manual page. XDMCP is a complex system that is not specific to Cygwin/X; further discussion of XDMCP is beyond the scope of this document. You may wish to read the Linux XDMCP HOWTO or the X Server XDMCP Options for more information.

예) XWin.exe :0 -query 192.168.0.200

※ root 사용자로 로그인 가능하게 하기.

/etc/X11/gdm/gdm-config 파일에서 [security] 섹션부분의 AllowRemoteRoot=false 를 true로 변경.

3. Displaying Remote Clients

Displaying remote X clients with Cygwin/X is nearly identical to displaying remote X clients with any other X Server. You may use the secure ssh method, or the unsecure telnet method (not recommended).

Secure ssh
On your Windows machine:

① Make sure you have the openssh package installed.

② Launch Cygwin/X

③ Run the following in an X terminal:

Username@CygwinHost ~
$ ssh -Y -l username remote_hostname_or_ip_address


④ Enter your password when prompted by ssh.

⑤ Your ssh session should now show you a shell prompt for your remote machine.

⑥ You can now launch remote X clients in your ssh session, for example, xterm& will launch an xterm running on your remote host that will display on your Cygwin/X screen.

⑦ Launch other remote clients in the same manner. I recommend starting the remote clients in the background, by appending & to the command name, so that you don't have to open several ssh sessions.

※ 체크사항

서버의 /etc/ssh/sshd_config 파일에서

#X11Forwarding no
#X11DisplayOffset 10
#X11UseLocalhost yes

부분을 아래와 같이 변경.

X11Forwarding yes
X11DisplayOffset 10
X11UseLocalhost yes

Unsecure Telnet
On your Windows machine:

① Make sure you have the inetutils package installed.

② Launch Cygwin/X

③ In an X terminal type /usr/X11R6/bin/xhost remote_hostname_or_ip_address

④ In an X terminal type /usr/bin/telnet remote_hostname_or_ip_address. Use the explicit path to ensure that Cygwin's telnet is run instead of Microsoft's telnet; Microsoft's telnet will crash on startup when run from Cygwin/X.

⑤ Login to your remote machine via your telnet session

⑥ In your telnet session type, DISPLAY=windows_hostname_or_ip_address:0.0

⑦ In your telnet session type, export DISPLAY

⑧ You can now launch remote X clients in your telnet session, for example, xterm& will launch an xterm running on your remote host that will display on your Cygwin/X screen.

⑨ Launch other remote clients in the same manner; I recommend starting the remote clients in the background, by appending & to the command name, so that you don't have to open several telnet sessions.

4. Run gonme-session over ssh

XWin &
export DISPLAY=:0
ssh -Y remoteserver -l user gnome-session

5. Cygwin/X에서 원격 X Window 로그아웃이 너무 느리다.

Windows-XP SP2 방화벽 체크
(제어판->방화벽->예외 탭 에서 TCP 포트 7100을 추가한다)

6. 참고사이트
- http://x.cygwin.com/docs/ug/using-remote-session.html
- Linux XDMCP HOWTO ( http://en.tldp.org/HOWTO/XDMCP-HOWTO )
2008/10/28 00:54 2008/10/28 00:54
Posted
Filed under About Knowledge/OS_Unix
KSH template ON SUN




==================================================================================
#!/usr/bin/ksh
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License, Version 1.0 only
# (the "License").  You may not use this file except in compliance
# with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
# Copyright 2006, 2007 Bernd Schemmer  All rights reserved.
# Use is subject to license terms.

# Notes:
#
# - use "scriptt.sh {-v} -h" to get the usage help
# - the main code starts after the line containing "main:"
#
# - replace "scriptt.sh" with the name of your script
# - change the parts marked with "???" and "??" to your need
#
# - use "scriptt.sh -H 2 >scriptt.sh.doc" to get the documentation
#
# - this is a Kornshell script - it may not function correctly in other shells
# - the script was written and tested with ksh88 but should also work in ksh93
#
##
# -----------------------------------------------------------------------------
##
## scriptt.sh - ??? script description ???
##
## Author: Bernd Schemmer (Bernd.Schemmer@gmx.de)
##
## Version: see variable ${__SCRIPT_VERSION} below
##          (see variable ${__SCRIPT_TEMPLATE_VERSION} for the template 
##           version used)
##
## Supported OS: Solaris and others
##
##
## Description
## 
## ???
##
## Configuration file
##
## This script supports a configuration file called <scriptname>.conf.
## The configuration file is searched in the working directory,
## the home directory of the user executing this script and /etc
## (in this order).
##
## The configuration file is read before the parameter are read.
##
## See the variable __CONFIG_PARAMETER below for the possible entries in 
## the config file.
## 
## Predefined parameter
##
## see the subroutines ShowShortUsage and ShowUsage 
##
##
## History:
##   ??.??.2007 v0.0.0.1 /bs
##     initial release
##
## script template History
## -----------------------
##   1.22.0 08.06.2006 /bs
##     public release; starting history for the script template
##
##   1.22.1 12.06.2006 /bs
##      added true/false to CheckYNParameter and ConvertToYesNo
## 
##   1.22.2. 21.06.2006 /bs
##      added the parameter -V
##      added the use of environment variables
##      added the variable __NO_TIME_STAMPS
##      added the variable __NO_HEADERS
##      corrected a bug in the function executeCommandAndLogSTDERR
##      added missing return commands
##
##   1.22.3 24.06.2006 /bs
##      added the function StartStop_LogAll_to_logfile
##      added the variable __USE_TTY (used in AskUser)
##      corrected an spelling error (dev/nul instead of /dev/null)
##
##   1.22.4 06.07.2006 /bs
##      corrected a bug in the parameter error handling routine
##
##   1.22.5 27.07.2006 /bs
##      corrected some minor bugs
##
##   1.22.6 09.08.2006 /bs
##      corrected some minor bugs
##
##   1.22.7 17.08.2006 /bs
##      add the CheckParameterCount function
##      added the parameter -T 
##      added long parameter support (e.g --help)
##
##   1.22.8 07.09.2006 /bs
##      added code to save the env variable LANG and set it temporary to C
##
##   1.22.9 20.09.2006 /bs
##      corrected code to save the env variable LANG and set it temporary to C
##   
##   1.22.10 21.09.2006 /bs
##      cleanup comments
##      the number of temporary files created automatically is now variable 
##        (see the variable __NO_OF_TEMPFILES)
##      added code to install the trap handler in all functions
##
##   1.22.11 19.10.2006 /bs
##      corrected a minor bug in AskUser (/c was not interpreted by echo)
##      corrected a bug in the handling of the parameter -S (-S was ignored)
##
##   1.22.12 31.10.2006 /bs
##      added the variable __REQUIRED_ZONE
##
##   1.22.13 13.11.2006 /bs
##      the template now uses TMP or TEMP if set for the temporary files
##
##   1.22.14 14.11.2006 /bs
##      corrected a bug in the function AskUser (the default was y not n)
##
##   1.22.15 21.11.2006 /bs
##      added initial support for other Operating Systems
##
##   1.22.16 05.07.2007 /bs
##      enhanced initial support for other Operating Systems
##      Support for other OS is still not fully tested!
##
##   1.22.17 06.07.2007 /bs
##      added the global variable __TRAP_SIGNAL
##
##   1.22.18 01.08.2007 /bs
##      __OS_VERSION and __OS_RELEASE were not set - corrected
##
##   1.22.19 04.08.2007 /bs
##      wrong function used to print "__TRAP_SIGNAL is \"${__TRAP_SIGNAL}\"" - fixed
##
##   1.22.20 12.09.2007 /bs
##      the script now checks the ksh version if running on Solaris
##      made some changes for compatibility with ksh93
##
##   1.22.21 18.09.2007 /bs
##      added the variable __FINISHROUTINES
##      changed __REQUIRED_ZONE to __REQUIRED_ZONES
##      added the variable __KSH_VERSION
##      reworked the trap handling
##
## ----------------
## Version variables
##
## __SCRIPT_VERSION - the version of your script 
##
typeset -r __SCRIPT_VERSION="v0.0.0.1"
##

## __SCRIPT_TEMPLATE_VERSION - version of the script template
##
typeset -r __SCRIPT_TEMPLATE_VERSION="1.22.20 20.09.2007"
##

## ----------------
##
## Predefined return codes:
##
##    1 - show usage and exit
##    2 - invalid parameter found
##
##  210 - 237 reserved for the runtime system
##  238 - unsupported Operating system
##  239 - script runs in a not supported zone
##  240 - internal error
##  241 - a command ended with an error (set -e is necessary to activate this trap)
##  242 - the current user is not allowed to execute this script
##  243 - invalid machine architecture
##  244 - invalid processor type
##  245 - invalid machine platform
##  246 - error writing the config file
##  247 - include script not found
##  248 - unsupported OS version
##  249 - Script not executed by root
##  250 - Script is already running
##
##  251 - QUIT signal received
##  252 - User break
##  253 - TERM signal received
##  254 - unknown external signal received
##

## ----------------
## Used environment variables
##
#
# The variable __USED_ENVIRONMENT_VARIABLES is used in the function ShowUsage
#
__USED_ENVIRONMENT_VARIABLES="
## __DEBUG_CODE
## __RT_VERBOSE_LEVEL
## __QUIET_MODE
## __VERBOSE_MODE
## __VERBOSE_LEVEL
## __OVERWRITE_MODE
## __USER_BREAK_ALLOWED
## __NO_TIME_STAMPS
## __NO_HEADERS
## __USE_COLORS
## __USE_RBAC
## __TEE_OUTPUT_FILE
"

#
# binaries and scripts used in this script:
#
# basename cat cp cpio cut dd dirname expr find grep id ln ls prtdiag pwd rebboot rm sed tee touch tty umount uname who zonename
#
# /usr/bin/pfexec
# /usr/ucb/whoami or $( whence whoami )
# /usr/openwin/bin/resize or $( whence resize )


# -----------------------------------------------------------------------------

# variables for the trap handler

__FUNCTION="main"

# alias to install the trap handler
#
# Note: The statement LINENO=${LINENO} is necessary to use the variable LINENO in the trap command
#
alias __settrap="  
  LINENO=\${LINENO}
  trap 'GENERAL_SIGNAL_HANDLER  1    \${LINENO} \${__FUNCTION}' 1
  trap 'GENERAL_SIGNAL_HANDLER  2    \${LINENO} \${__FUNCTION}' 2
  trap 'GENERAL_SIGNAL_HANDLER  3    \${LINENO} \${__FUNCTION}' 3
  trap 'GENERAL_SIGNAL_HANDLER 15    \${LINENO} \${__FUNCTION}' 15
"


##
## ----------------
## ##### general hints
##
## Do not use variable names beginning with __ (these are reserved for
## internal use)
##


# -----------------------------------------------------------------------------
## __KSH_VERSION - ksh version (either 88 or 93)
##
  __KSH_VERSION=88 ; f() { typeset __KSH_VERSION=93 ; } ; f ; 

# save the language setting and switch the language temporary to C
#
__SAVE_LANG="${LANG}"
LANG=C
export LANG

# -----------------------------------------------------------------------------
## ##### constants
##
## __TRUE - true (0)
## __FALSE - false (1)
##
typeset -r __TRUE=0
typeset -r __FALSE=1


## ----------------
## internal variables
##
## __TRAP_SIGNAL - current trap caught by the trap handler
##   This is a global variable that can be used in the exit routines
##
__TRAP_SIGNAL=""


# -----------------------------------------------------------------------------
## __USE_RBAC - set this variable to ${__TRUE} to execute this script 
##   with RBAC
##   default is ${__FALSE}
##
__USE_RBAC=${__USE_RBAC:=${__FALSE}}

# -----------------------------------------------------------------------------
# use the parameter --tee to automatically call the script and pipe 
# all output to tee
#
__TEE_OUTPUT_FILE="${__TEE_OUTPUT_FILE:=/var/tmp/$( basename $0 ).tee.log}"

if [ "$1"x = "-T"x -o "$1"x = "--tee"x ] ; then
# Note: If you need the parent PID save it here
#
   __PPID=$PPID ; export __PPID

  echo "Saving STDOUT and STDERR to \"${__TEE_OUTPUT_FILE}\" ..."
  shift
  exec $0 $@ 2>&1 | tee -a "${__TEE_OUTPUT_FILE}"
  exit $?
fi

[ "${__PPID}"x = ""x ] && __PPID=$PPID ; export __PPID

# -----------------------------------------------------------------------------
#
# Set the variable ${__USE_RBAC} to ${__TRUE} to activate RBAC support
#
# Allow the use of RBAC to control who can access this script. Useful for
# administrators without root permissions
#
if [ "${__USE_RBAC}" = "${__TRUE}" ] ; then
  if [ "$_" != "/usr/bin/pfexec" -a -x /usr/bin/pfexec ]; then
    /usr/bin/pfexec $0 $*
    exit $?
  else
    echo "${0%%*/} ERROR: /usr/bin/pfexec not found or not executable!" >&2 
    exit 238 
  fi
fi

# -----------------------------------------------------------------------------
## 
## ##### defined variables that may be changed
##


## __DEBUG_CODE - code executed at start of every sub routine
##   Note: Use always "__DEBUG_CODE="eval ..." if you want to use variables or aliases
##         Default debug code : none
##
#  __DEBUG_CODE=""

## __FUNCTION_INIT - code executed at start of every sub routine
##   (see the hints for __DEBUG_CODE)
##         Default init code : install the trap handlers
##
# __FUNCTION_INIT=""
 __FUNCTION_INIT=" eval __settrap"
 

##
## sample debug code:
## __DEBUG_CODE="  eval echo Entering the subroutine \${__FUNCTION} ...  "
##
## Note: Use an include script for more complicate debug code, e.g.
## __DEBUG_CODE=" eval . /var/tmp/mydebugcode"
##

## __CONFIG_PARAMETER
##   The variable __CONFIG_PARAMETER contains the configuration variables
##
## The defaults for these variables are defined here. You 
## can use a config file to overwrite the defaults. 
##
## Use the parameter -C to create a default configuration file
##
## Note: The config file is read and interpreted via ". configfile"  
##       therefore you can add also some code here
##
__CONFIG_PARAMETER='

# extension for backup files

  DEFAULT_BACKUP_EXTENSION=".$$.backup"

# ??? example variables for the configuration file - change to your need


# master server with the directories to synchronize
# The rsync daemon must run either on this host or on localhost
# If the rsync daemon runs on localhost the master server must export
# the directories to synchronize using NFS. In this case the directories
# on the master server must be the same as on the rsync client
#
# overwritten by the parameter -m
  DEFAULT_MASTER_SERVER="linst2.rze.de.db.com"

# server with the rsync daemon. This is either the master server or
# localhost
#
# overwritten by the parameter -s
  DEFAULT_RSYNC_SERVER="localhost"

  
# only change the following variables if you know what you are doing #


# no further internal variables defined yet
#
# Note you can redefine any variable that is initialized before calling
# ReadConfigFile here!
'
# end of config parameters


## __SHORT_DESC - short description (for help texts, etc)
##   Change to your need
##
typeset -r __SHORT_DESC="??? short description ???"

## __LONG_USAGE_HELP - Additional help if the script is called with 
##   the parameter "-v -h"
##
##   Note: To use variables in the help text use the variable name without
##         an escape character, eg. ${OS_VERSION}
##
__LONG_USAGE_HELP='
      [??? add additional parameter here ???] 

'

## __SHORT_USAGE_HELP - Additional help if the script is called with the parameter "-h"
##
##   Note: To use variables in the help text use the variable name without an escape
##         character, eg. ${OS_VERSION}
##
__SHORT_USAGE_HELP='
                    [??? add additional parameter here ???] 
'


## __MUST_BE_ROOT - run script only by root (def.: false)
##   set to ${__TRUE} for scripts that must be executed by root only
##
__MUST_BE_ROOT=${__FALSE}

## __REQUIRED_USERID - required userid to run this script (def.: none)
##   use blanks to separate multiple userids
##   e.g. "oracle dba sysdba"
##   "" = no special userid required
##
__REQUIRED_USERID=""

## __REQUIRED_ZONES - required zones (either global, non-global or local 
##    or the names of the valid zones)
##   (def.: none) 
##   "" = no special zone required
##
__REQUIRED_ZONES=""

## __ONLY_ONCE - run script only once at a time (def.: false)
##   set to ${__TRUE} for scripts that can not run more than one instance at 
##   the same time
##
__ONLY_ONCE=${__FALSE}

## __ REQUIRED_OS - required OS (uname -s) for the script (def.: none)
##    use blanks to separate the OS names if the script runs under multiple OS
##    e.g. "SunOS"
##
__REQUIRED_OS=""


## __REQUIRED_OS_VERSION - required OS version for the script (def.: none)
##   minimum OS version necessary, e.g. 5.10
##   "" = no special version necessary
##
__REQUIRED_OS_VERSION=""

## __REQUIRED_MACHINE_PLATFORM - required machine platform for the script (def.: none)
##   required machine platform (uname -i) , e.g "i86pc"; use blanks to separate 
##   the multiple machine types, e.g "Sun Fire 3800 i86pc"
##   "" = no special machine type necessary
##
__REQUIRED_MACHINE_PLATFORM=""

## __REQUIRED_MACHINE_CLASS - required machine class for the script (def.: none)
##   required machine class (uname -m) , e.g "i86pc" ; use blanks to separate  
##   the multiple machine classes, e.g "sun4u i86pc"
##   "" = no special machine class necessary
##
__REQUIRED_MACHINE_CLASS=""

## __REQUIRED_MACHINE_ARC - required machine architecture for the script (def.: none)
##   required machine architecture (uname -p) , e.g "i386" ; use blanks to separate 
##   the machine architectures if more than one entry, e.g "sparc i386"
##   "" = no special machine architecture necessary
##
__REQUIRED_MACHINE_ARC=""

## __VERBOSE_LEVEL - count of -v parameter (def.: 0)
##
typeset -i __VERBOSE_LEVEL=${__VERBOSE_LEVEL:=0}

## __RT_VERBOSE_LEVEL - level of -v for runtime messages (def.: 1)
##
##   e.g. 1 = -v -v is necessary to print info messages of the runtime system
##        2 = -v -v -v is necessary to print info messages of the runtime system
##
typeset -i __RT_VERBOSE_LEVEL=${__RT_VERBOSE_LEVEL:=1}

## __QUIET_MODE - do not print messages to STDOUT (def.: false)
##   use the parameter -q/+q to change this variable
##
__QUIET_MODE=${__QUIET_MODE:=${__FALSE}}

## __VERBOSE_MODE - print verbose messages (def.: false)
##   use the parameter -v/+v to change this variable  
##
__VERBOSE_MODE=${__VERBOSE_MODE:=${__FALSE}}

## __NO_TIME_STAMPS - Do not use time stamps in the messages (def.: false)
##
__NO_TIME_STAMPS=${__NO_TIME_STAMPS:=${__FALSE}}

## __NO_HEADERS - Do not print headers and footers (def.: false)
##
__NO_HEADERS=${__NO_HEADERS:=${__FALSE}}

## __FORCE - do the action anyway (def.: false)
##   If this variable is set to ${__TRUE} the function "die" will return 
##   if called with an RC not zero (instead of aborting the script)
##   use the parameter -f/+f to change this variable
##
__FORCE=${__FALSE}

## __USE_COLORS - use colors (def.: false) 
##   use the parameter -a/+a to change this variable
##
__USE_COLORS=${__USE_COLORS:=${__FALSE}}

## __USER_BREAK_ALLOWED - CTRL-C aborts the script or not (def.: true)
##   (no parameter to change this variable)
##
__USER_BREAK_ALLOWED=${__USER_BREAK_ALLOWED:=${__TRUE}}

## __NOECHO - turn echo off while reading input from the user
##   do not echo the user input in AskUser if __NOECHO is set to ${__TRUE}
##
__NOECHO=${__FALSE}

## __USE_TTY - write prompts and read user input from /dev/tty (def.: false)
##   If __USE_TTY is ${__TRUE} the function AskUser writes the prompt to /dev/tty 
##   and the reads the user input from /dev/tty . This is useful if STDOUT is 
##   redirected to a file.
##
__USE_TTY=${__FALSE}

## __OVERWRITE mode - overwrite existing files or not (def.: false)
##   use the parameter -O/+O to change this variable
##
__OVERWRITE_MODE=${__OVERWRITE_MODE:=${__FALSE}}

## __DEBUG_MODE - use single step mode for main (def.: false)
##   use the parameter -D/+D to change this variable
##
__DEBUG_MODE=${__FALSE}
__SCRIPT_ARRAY[0]=0

## __TEMPDIR - directory for temporary files
##
__TEMPDIR="${TMP:-${TEMP:-/tmp}}"

## __NO_OF_TEMPFILES
##   number of automatically created tempfiles that are deleted at program end
##   (def. 2)
##   Note: The variable names for the tempfiles are __TEMPFILE1, __TEMPFILE2, etc.
##
__NO_OF_TEMPFILES=2

## __LIST_OF_TMP_MOUNTS - list of mounts that should be umounted at program end
##
__LIST_OF_TMP_MOUNTS=""

## __LIST_OF_TMP_DIRS - list of directories that should be removed at program end
##
__LIST_OF_TMP_DIRS=""

## __LIST_OF_TMP_FILES - list of files that should be removed at program end
##
__LIST_OF_TMP_FILES=""

## __EXITROUTINES - list of routines that should be executed before the script ends
##   Note: These routines are called *before* temp files, temp directories, and temp 
##         mounts are removed
##
__EXITROUTINES=""

## __FINISHROUTINES - list of routines that should be executed before the script ends
##   Note: These routines are called *after* temp files, temp directories, and temp
##         mounts are removed
##
__FINISHROUTINES=""

## __REBOOT_REQUIRED - set to true to reboot automatically at 
##   script end (def.: false)
##
__REBOOT_REQUIRED=${__FALSE}

## __REBOOT_PARAMETER - parameter for the reboot command (def.: none)
##
__REBOOT_PARAMETER=""

## __PRINT_LIST_OF_WARNINGS_MSGS - print the list of warning messages at program end (def.: false)
##
__PRINT_LIST_OF_WARNINGS_MSGS=${__FALSE}

## __PRINT_LIST_OF_ERROR_MSGS - print the list of error messages at program end (def.: false)
##
__PRINT_LIST_OF_ERROR_MSGS=${__FALSE}

## __PRINT_SUMMARIES - print error/warning msg summaries at script end
##
##   print error and/or warning message summaries at program end
##   known values:
##       0 = do not print summaries
##       1 = print error msgs,
##       2 = print warning msgs
##       3 = print error and warning mgs
##   use the parameter -S to change this variable
##
__PRINT_SUMMARIES=0

## __MAINRC - return code of the program 
##
__MAINRC=0


# -----------------------------------------------------------------------------
#

# -----------------------------------------------------------------------------
# init the global variables
#

## ##### defined variables that should not be changed
##

# init the variable for the TRAP handlers  
#   __INCLUDE_SCRIPT_RUNNING contains the name of the included script if 
#   a sourced-in script is currently running
#
__INCLUDE_SCRIPT_RUNNING=""

# 
# internal variables for push/pop
#
typeset -i __STACK_POINTER=0
__STACK[0]=${__STACK_POINTER}

#
# internal variables for the single-step routine
#
typeset -i __BREAKPOINT_LINE=0 
typeset -i __STEP_COUNT=0
typeset -i __TRACE_COUNT=0
__DEBUG_HISTFILE="/tmp/ksh.history.$$"

# delete the history file used in the debug routine at program end
__LIST_OF_TMP_FILES="${__LIST_OF_TMP_FILES} ${__DEBUG_HISTFILE}"

# variable used for input by the user
#
__USER_RESPONSE_IS=""

# __STTY_SETTINGS
#   saved stty settings before switching off echo in AskUser
#
__STTY_SETTINGS=""

## __SCRIPTNAME - name of the script without the path
##
typeset -r __SCRIPTNAME="${0##*/}"

## __SCRIPTDIR - path of the script (as entered by the user!)
##
__SCRIPTDIR="${0%/*}"

## __REAL_SCRIPTDIR - path of the script (real path, maybe a link)
##
__REAL_SCRIPTDIR=$( cd -P -- "$(dirname -- "$(command -v -- "$0")")" && pwd -P )

## __CONFIG_FILE - name of the config file
##   (use ReadConfigFile to read the config file; 
##   use WriteConfigFile to write it)
##
__CONFIG_FILE="${__SCRIPTNAME%.*}.conf"

## __HOSTNAME - hostname 
##
__HOSTNAME="$( uname -n )"

## __NODENAME - nodename 
##
__NODENAME=${__HOSTNAME}
[ -f /etc/nodename ] && __NODENAME="$( cat /etc/nodename )"

## __OS - Operating system (e.g. SunOS)
##
__OS="$( uname -s )"

## __ZONENAME - name of the current zone if running in Solaris 10 or newer
## 

## __OS_VERSION - Operating system version (e.g 5.8)
##

## __OS_RELEASE - Operating system release (e.g. Generic_112233-08)
##

## __MACHINE_CLASS - Machine class (e.g sun4u)
##

## __MACHINE_PLATFORM - hardware platform (e.g. SUNW,Ultra-4)
##

## __MACHINE_SUBTYPE - machine type (e.g  Sun Fire 3800)
##

## __MACHINE_ARC - machine architecture (e.g. sparc)
##

## __RUNLEVEL - current runlevel
##
# __RUNLEVEL="$( set -- $( who -r )  ; echo $7 )"

case ${__OS} in

    "SunOS" ) 
       __ZONENAME="$( zonename 2>/dev/null )" 
       __OS_VERSION="$( uname -r )" 
       __OS_RELEASE="$( uname -v )"
       __MACHINE_CLASS="$( uname -m )"
       __MACHINE_PLATFORM="$( uname -i )"
       [  -x /usr/platform/${__MACHINE_PLATFORM}/sbin/prtdiag ] &&   \
         ( set -- $( /usr/platform/${__MACHINE_PLATFORM}/sbin/prtdiag | grep "System Configuration" ) ; shift 5; echo $* ) 2>/dev/null | read  __MACHINE_SUBTYPE
         __MACHINE_ARC="$( uname -p )"
       __RUNLEVEL=$( who -r  2>/dev/null | tr -s " " | cut -f8 -d " " ) 
       ;;
     
    "AIX" ) 
       __ZONENAME=""
       __MACHINE_PLATFORM="$( oslevel )" 
       __OS_VERSION="$( oslevel -r )"
       __OS_RELEASE="$( uname -v )"
       __MACHINE_CLASS="$( uname -m )"
       __MACHINE_PLATFORM="$( uname -M )"
       __MACHINE_SUBTYPE=""
       __MACHINE_ARC="$( uname -p )"
       __RUNLEVEL=$( who -r  2>/dev/null | tr -s " " | cut -f8 -d " " ) 
       ;;

      
    "Linux" ) 
       __ZONENAME=""
       __OS_VERSION="$( uname -r )"
       __OS_RELEASE="$( uname -v )" 
       __MACHINE_CLASS="$( uname -m )"
       __MACHINE_PLATFORM="$( uname -i )"
       __MACHINE_SUBTYPE=""
       __MACHINE_ARC="$( uname -p )"
       __RUNLEVEL=$( who -r  2>/dev/null | tr -s " " | cut -f3 -d " " ) 
       ;;
     
    * ) 
       __ZONENAME=""
       __MACHINE_PLATFORM=""
       __MACHINE_CLASS="" 
       __MACHINE_PLATFORM=""
       __MACHINE_SUBTYPE=""
       __MACHINE_ARC=""
       __RUNLEVEL="?"
       ;;
     
esac


## __START_DIR - working directory when starting the script
##
__START_DIR="$( pwd )"

## __LOGFILE - fully qualified name of the logfile used
##   use the parameter -l to change the logfile
##
if [ -d /var/tmp ] ; then
  __DEF_LOGFILE="/var/tmp/${__SCRIPTNAME%.*}.LOG"
else
  __DEF_LOGFILE="/tmp/${__SCRIPTNAME%.*}.LOG"
fi

__LOGFILE="${__DEF_LOGFILE}"

# __GLOBAL_OUTPUT_REDIRECTION
#   status variable used by StartStop_LogAll_to_logfile
#
__GLOBAL_OUTPUT_REDIRECTION=""

     
# lock file (used if ${__ONLY_ONCE} is ${__TRUE})
# Note: This is only a symbolic link
#
__LOCKFILE="/tmp/${__SCRIPTNAME}.lock"
__LOCKFILE_CREATED=${__FALSE}

## __NO_OF_WARNINGS - Number of warnings found
##
typeset -i __NO_OF_WARNINGS=0

## __LIST_OF_WARNINGS - List of warning messages
##
__LIST_OF_WARNINGS=""

## __NO_OF_ERRORS - Number of errors found
##
typeset -i __NO_OF_ERRORS=0

## __LIST_OF_ERRORS - List of error messages
##
__LIST_OF_ERRORS=""

## __LOGON_USERID - ID of the user opening the session  
##
__LOGIN_USERID="$( set -- $( who am i ) ; echo $1 )"
[ "${__LOGIN_USERID}"x = ""x ] && __LOGIN_USERID="${LOGNAME}"

## __USERID - ID of the user executing this script (e.g. xtrnaw7)
##
__USERID="${__LOGIN_USERID}"
if [ "${__OS}"x = "SunOS"x ] ; then
  [ -x /usr/ucb/whoami ] && __USERID="$( /usr/ucb/whoami )"
else
  __USERID="$( whoami )"
fi


# -----------------------------------------------------------------------------
# color variables

## Foreground Color variables:
## __COLOR_FG_BLACK, __COLOR_FG_RED,     __COLOR_FG_GREEN, __COLOR_FG_YELLOW
## __COLOR_FG_BLUE,  __COLOR_FG_MAGENTA, __COLOR_FG_CYAN,  __COLOR_FG_WHITE
##
## Background Color variables:
## __COLOR_BG_BLACK, __COLOR_BG_RED,     __COLOR_BG_GREEN, __COLOR_BG_YELLOW
## __COLOR_BG_BLUE,  __COLOR_BG_MAGENTA, __COLOR_BG_CYAN,  __COLOR_BG_WHITE
##

__COLOR_FG_BLACK="\033[30m"
__COLOR_FG_RED="\033[31m"
__COLOR_FG_GREEN="\033[32m"
__COLOR_FG_YELLOW="\033[33m"
__COLOR_FG_BLUE="\033[34m"
__COLOR_FG_MAGENTA="\033[35m"
__COLOR_FG_CYAN="\033[36m"
__COLOR_FG_WHITE="\033[37m"

__COLOR_BG_BLACK="\033[40m"
__COLOR_BG_RED="\033[41m"
__COLOR_BG_GREEN="\033[42m"
__COLOR_BG_YELLOW="\033[43m"
__COLOR_BG_BLUE="\033[44m"
__COLOR_BG_MAGENTA="\033[45m"
__COLOR_BG_CYAN="\033[46m"
__COLOR_BG_WHITE="\033[47m"

##
## Colorattributes:
## __COLOR_OFF, __COLOR_BOLD, __COLOR_NORMAL, - normal, __COLOR_UNDERLINE
## __COLOR_BLINK, __COLOR_REVERSE, __COLOR_INVISIBLE
##

__COLOR_BOLD="\033[1m"
__COLOR_NORMAL="\033[2m"
__COLOR_UNDERLINE="\033[4m"
__COLOR_BLINK="\033[5m"
__COLOR_REVERSE="\033[7m"
__COLOR_INVISIBLE="\033[8m"
__COLOR_OFF="\033[0;m"


# position cursor:       ESC[row,colH or ESC[row;colf  (1,1 = upper left corner)
# Clear rest of line:    ESC[K
# Clear screen:          ESC[2J
# Save Cursor Pos        ESC[s
# Restore Cursor Pos     ESC[u
# Cursor Up # lines      ESC{colsA
# Cursor down # lines    ESC{colsB
# Cursor right # columns ESC{colsC
# Cursor left # columns  ESC{colsD
# Get Cursor Pos         ESC[6n
#

# -----------------------------------------------------------------------------

## 
## ##### defined sub routines
##

## --------------------------------------
## ReadConfigFile
##
## read the config file
##
## usage: ReadConfigFile [configfile]
##
## where:   configfile - name of the config file
##          default: search ${__CONFIG_FILE} in the current directory,
##          in the home directory, and in /etc (in this order)
##
## returns: ${__TRUE} - ok config read
##          ${__FALSE} - error config file not found or not readable
##
function ReadConfigFile {
  typeset __FUNCTION="ReadConfigFile"; ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset THIS_CONFIG="$1"
  typeset THISRC=${__FALSE}
  
  if [ "${THIS_CONFIG}"x = ""x ] ; then
    THIS_CONFIG="./${__CONFIG_FILE}"
    [ ! -f "${THIS_CONFIG}" ] && THIS_CONFIG="${HOME}/${__CONFIG_FILE}"
    [ ! -f "${THIS_CONFIG}" ] && THIS_CONFIG="/etc/${__CONFIG_FILE}"
  fi

  if [ -f "${THIS_CONFIG}" ] ; then
    LogHeader "Reading the config file \"${THIS_CONFIG}\" ..." 

    includeScript "${THIS_CONFIG}"

    THISRC=${__TRUE}    
  else
    LogHeader "No config file (\"${__CONFIG_FILE}\") found (use -C to create a default config file)"
  fi

  return ${THISRC}
}

## --------------------------------------
## WriteConfigFile
##
## write the variable ${__CONFIG_PARAMETER} to the config file
##
## usage: WriteConfigFile [configfile]
##
## where:  configfile - name of the config file
##         default: write ${__CONFIG_FILE} in the current directory
##
## returns: ${__TRUE} - ok config file written
##          ${__FALSE} - error writing the config file
##
function WriteConfigFile {
  typeset __FUNCTION="WriteConfigFile" ; ${__FUNCTION_INIT} ; ${__DEBUG_CODE} 

  typeset THIS_CONFIG_FILE="$1"
  typeset THISRC=${__FALSE}
  
  [ "${THIS_CONFIG_FILE}"x = ""x ] && THIS_CONFIG_FILE="./${__CONFIG_FILE}"

  [ -f "${THIS_CONFIG_FILE}" ] &&  BackupFileIfNecessary "${THIS_CONFIG_FILE}"
  LogMsg "Writing the config file \"${THIS_CONFIG_FILE}\" ..." 
   
cat <<EOT >"${THIS_CONFIG_FILE}"
# config file for $0
${__CONFIG_PARAMETER}
EOT
  THISRC=$?
  
  return ${THISRC}
}

## --------------------------------------
## NoOfStackElements
##
## return the no. of stack elements
##
## usage: NoOfStackElements; var=$?
##
## returns: no. of elements on the stack
##
## Note: NoOfStackElements, FlushStack, push and pop use only one global stack!
##
function NoOfStackElements {
  typeset __FUNCTION="NoOfStackElements";  ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  return ${__STACK_POINTER}
}

## --------------------------------------
## FlushStack
##
## flush the stack
##
## usage: FlushStack
##
## returns: no. of elements on the stack before flushing it
##
## Note: NoOfStackElements, FlushStack, push and pop use only one global stack!
##
function FlushStack {
  typeset __FUNCTION="FlushStack";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset THISRC=${__STACK_POINTER}
  __STACK_POINTER=0
  return ${THISRC}
}

## --------------------------------------
## push
##
## push one or more values on the stack
##
## usage: push value1 [...] [value#]
##
## returns: 0
##
## Note: NoOfStackElements, FlushStack, push and pop use only one global stack!
##
function push {
  typeset __FUNCTION="push";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

   while [ $# -ne 0 ] ; do
    (( __STACK_POINTER=__STACK_POINTER+1 ))
    __STACK[${__STACK_POINTER}]="$1"
    shift
  done

  return 0
}

## --------------------------------------
## pop
##
## pop one or more values from the stack
##
## usage: pop variable1 [...] [variable#]
##
## returns: 0
##
## Note: NoOfStackElements, FlushStack, push and pop use only one global stack!
##
function pop {
  typeset __FUNCTION="pop";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset NEWALUE=""

  while [ $# -ne 0 ] ; do
    if [ ${__STACK_POINTER} -eq 0 ] ; then
      NEWVALUE=""
    else
      NEWVALUE="${__STACK[${__STACK_POINTER}]}"
      (( __STACK_POINTER=__STACK_POINTER-1 ))
    fi
    eval $1="\"${NEWVALUE}\""
    shift
  done

  return 0
}

## --------------------------------------
## push_and_set
##
## push a variable to the stack and set the variable to a new value
##
## usage: push_and_set variable new_value
##
## returns: 0
##
## Note: NoOfStackElements, FlushStack, push and pop use only one global stack!
##
function push_and_set {
  typeset __FUNCTION="push_and_set";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  if [ $# -ne 0 ] ; then
    typeset VARNAME="$1"
    eval push \$${VARNAME}
     
    shift
    eval ${VARNAME}="\"$*\""
  fi
  
  return 0
}


## --------------------------------------
## CheckYNParameter
##
## check if a parameter is y, n, 0, or 1
##
## usage: CheckYNParameter parameter
##
## returns: ${__TRUE} - the parameter is equal to yes
##          ${__FALSE} - the parameter is equal to no
##
function CheckYNParameter {
  typeset __FUNCTION="CheckYNParameter";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset THISRC=255
  
  case $1 in
   "y" | "Y" | "yes" | "YES" | "true"  | "TRUE"  | 0 ) THISRC=${__TRUE} ;;
   "n" | "N" | "no"  | "NO"  | "false" | "FALSE" | 1 ) THISRC=${__FALSE} ;;
   * ) THISRC=255 ;;
  esac
  return ${THISRC}
}


## --------------------------------------
## ConvertToYesNo
##
## convert the value of a variable to y or n
##
## usage: ConvertToYesNo parameter
##
## returns: 0
##          prints y, n or ? to STDOUT
##
function ConvertToYesNo {
  typeset __FUNCTION="ConvertToYesNo";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  case $1 in
   "y" | "Y" | "yes" | "YES" | "true"  | "TRUE"  | 0 ) echo "y" ;;
   "n" | "N" | "no"  | "NO"  | "false" | "FALSE" | 1 ) echo "n" ;;
   * ) echo "?" ;;
  esac
  
  return 0
}

## --------------------------------------
## InvertSwitch
##
## invert a switch from true to false or vice versa
##
## usage: InvertSwitch variable
##
## returns 0
##         switch the variable "variable" from ${__TRUE} to
##         ${__FALSE} or vice versa
##
function InvertSwitch {
  typeset __FUNCTION="InvertSwitch";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  eval "[ \$$1 -eq ${__TRUE} ] && $1=${__FALSE} || $1=${__TRUE} "
  
  return 0
}

  
## --------------------------------------
## CheckInputDevice
##
## check if the input device is a terminal
##
## usage: CheckInputDevice
##
## returns: 0 - the input device is a terminal (interactive)
##          1 - the input device is NOT a terminal
##
function CheckInputDevice {
  typeset __FUNCTION="CheckInputDevice";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  tty -s
  return $?
}
  
## --------------------------------------
## GetProgramDirectory
##
## get the directory where a program resides
##
## usage: GetProgramDirectory [programpath/]programname [resultvar]
##
## returns: 0
##          the variable PRGDIR contains the directory with the program
##          if the parameter resultvar is missing
##
function GetProgramDirectory {
  typeset __FUNCTION="GetProgramDirectory";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset PRG=""
  typeset RESULTVAR=$2
    
  if [ ! -L $1 ] ; then
    PRG=$( cd -P -- "$(dirname -- "$(command -v -- "$1")")" && pwd -P )
  else  
# resolve links - $1 may be a softlink
    PRG="$1"
   
    while [ -h "$PRG" ] ; do
      ls=$(ls -ld "$PRG")
      link=$( expr "$ls" : '.*-> \(.*\)$' )
      if expr "$link" : '.*/.*' > /dev/null; then
        PRG="$link"
      else
        PRG=$(dirname "$PRG")/"$link"
      fi
    done
    PRG="$(dirname ${PRG})"
  fi

  if [ "${RESULTVAR}"x != ""x ] ; then
     eval ${RESULTVAR}=\"${PRG}\"
  else 
    PRGDIR="${PRG}"
  fi
  
  return 0
}

## --------------------------------------
## substr
##
## get a substring of a string
##
## usage: variable=$( substr sourceStr pos length )
##     or substr sourceStr pos length resultStr
##
## returns: 1 - parameter missing
##          0 - parameter okay
##
function substr {
  typeset __FUNCTION="substr";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset resultstr=""
  typeset THISRC=1

  if [ "$1"x != ""x ] ; then 
    typeset s="$1"
    typeset p="$2"
    typeset l="$3"
    [ "$l"x = ""x ] && l=${#s}
    [ "$p"x = ""x ] && p=1
    resultstr="$( echo $s | cut -c${p}-$((${p}+${l}-1)) )"
    THISRC=0
  else
    THISRC=1
    resultstr="$1"
  fi

  if [ "$4"x != ""x ] ; then
    eval $4=\"${resultstr}\" 
  else
    echo "${resultstr}"
  fi

  return ${THISRC}
}

## --------------------------------------
## replacestr
##
## replace a substring with another substring
##
## usage: variable=$( replacestr sourceStr oldsubStr newsubStr )
##     or replacestr sourceStr oldsubStr newsubStr resultvariable
##
## returns: 0 - substring replaced
##          1 - substring not found
##          3 - error, parameter missing
##
##          writes the substr to STDOUT if resultvariable is missing
##
function replacestr {
  typeset __FUNCTION="replacestr";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset THISRC=3
   
  typeset sourcestring="$1"
  typeset oldsubStr="$2"
  typeset newsubStr="$3"

  if [ "${sourcestring}"x != ""x -a "${oldsubStr}"x != ""x ] ; then
    if [[ "${sourcestring}" == *${oldsubStr}* ]] ; then
      sourcestring="${sourcestring%%${oldsubStr}*}${newsubStr}${sourcestring#*${oldsubStr}}" 
      THISRC=0
    else
      THISRC=1
    fi
  fi

  if [ "$4"x != ""x ] ; then
    eval $4=\"${sourcestring}\" 
  else
    echo "${sourcestring}"
  fi

  return ${THISRC}
}

## --------------------------------------
## pos
##
## get the first position of a substring in a string
##
## usage: pos searchstring sourcestring
##
## returns: 0 - searchstring is not part of sourcestring
##          else the position of searchstring in sourcestring
##
function pos {
  typeset __FUNCTION="pos";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset searchstring="$1"
  typeset sourcestring="$2"
 
  if [[ "${sourcestring}" == *${searchstring}* ]] ; then
    typeset f="${sourcestring%%${searchstring}*}"
    return $((  ${#f}+1 ))
  else
    return 0
  fi
}

## --------------------------------------
## lastpos
##
## get the last position of a substring in a string
##
## usage: lastpos searchstring sourcestring
##
## returns: 0 - searchstring is not part of sourcestring
##          else the position of searchstring in sourcestring
##
function lastpos {
  typeset __FUNCTION="lastpos";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset searchstring="$1"
  typeset sourcestring="$2"

  if [[ "${sourcestring}" == *${searchstring}* ]] ; then
    typeset f="${sourcestring%${searchstring}*}"
    return $((  ${#f}+1 ))
  else 
    return  0
  fi
}


## --------------------------------------
## isNumber
##
## check if a value is an integer 
##
## usage: isNumber testValue 
##
## returns: ${__TRUE} - testValue is a number else not
##
function isNumber {
  typeset __FUNCTION="isNumber";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset TESTVAR="$(echo "$1" | sed 's/[0-9]*//g' )"
  [ "${TESTVAR}"x = ""x ] && return ${__TRUE} || return ${__FALSE}
}

## --------------------------------------
## ConvertToHex
##
## convert the value of a variable to a hex value
##
## usage: ConvertToHex value
##
## returns: 0
##          prints the value in hex to STDOUT
##
function ConvertToHex {
  typeset __FUNCTION="ConvertToHex";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset -i16 HEXVAR
  HEXVAR="$1"
  echo ${HEXVAR##*#}
  
  return 0
}  

## --------------------------------------
## ConvertToOctal
##
## convert the value of a variable to a octal value
##
## usage: ConvertToOctal value
##
## returns: 0
##          prints the value in octal to STDOUT
##
function ConvertToOctal {
  typeset __FUNCTION="ConvertToOctal";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset -i8 OCTVAR
  OCTVAR="$1"
  echo ${OCTVAR##*#}
  
  return 0
}  

## --------------------------------------
## ConvertToBinary
##
## convert the value of a variable to a binary value
##
## usage: ConvertToBinary value
##
## returns: 0
##          prints the value in binary to STDOUT
##
function ConvertToBinary {
  typeset __FUNCTION="ConvertToBinary";  ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset -i2 BINVAR
  BINVAR="$1"
  echo ${BINVAR##*#}
  
  return 0
}  


## --------------------------------------
## toUppercase
##
## convert a string to uppercase
##
## usage: toUppercase sourceString | read resultString
##    or   targetString=$( toUppercase sourceString )
##    or   toUppercase sourceString resultString
##
## returns: 0
##          writes the converted string to STDOUT if resultString is missing
##
function toUppercase {
  typeset __FUNCTION="toUppercase";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset -u testvar="$1"

  if [ "$2"x != ""x ] ; then
    eval $2=\"${testvar}\" 
  else
    echo "${testvar}"
  fi
  
  return 0
}

## --------------------------------------
## toLowercase
##
## convert a string to lowercase
##
## usage: toLowercase sourceString | read resultString
##    or   targetString=$( toLowercase sourceString )
##    or   toLowercase sourceString resultString
##
## returns: 0
##          writes the converted string to STDOUT if resultString is missing
##
function toLowercase {
  typeset __FUNCTION="toLowercase";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset -l testvar="$1"

  if [ "$2"x != ""x ] ; then
    eval $2=\"${testvar}\" 
  else
    echo "${testvar}"
  fi
  
  return 0
}


## --------------------------------------
## StartStop_LogAll_to_logfile
##
## redirect STDOUT and STDERR into a file
##
## usage: StartStop_LogAll_to_logfile [start|stop] logfile
##
## returns: 0 - okay, redirection started / stopped
##          1 - error, can not write to the logfile
##          2 - invalid usage (to much or not enough parameter)
##          3 - invalid parameter 
##
## To explicitly write to STDOUT after calling this function with the 
## parameter "start" use 
##   echo "This goes to STDOUT" >&3
##
## To explicitly write to STDERR after calling this function with the 
## parameter "start" use 
##   echo "This goes to STDERR" >&4
##
function StartStop_LogAll_to_logfile {
  typeset __FUNCTION="StartStop_LogAll_to_logfile";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset THISRC=0
  
  if [ $# -ne 0 ] ; then
    case $1 in

     'start' ) 
        if [ $# -gt 1 ] ; then
          touch "$2" 2>/dev/null
          if [ $? -eq 0 ] ; then
            LogInfo "Logging STDOUT and STDERR to \"$2\" ... "
            exec 3>&1
            exec 4>&2
            if [ "${__OVERWRITE_MODE}" = "${__TRUE}" ] ; then
              exec 1>$2 2>&1
            else
              exec 1>>$2 2>&1
            fi
            __GLOBAL_OUTPUT_REDIRECTION="$2"
          else
            THISRC=1
          fi
        else
          THISRC=2
        fi
        ;;

      'stop' )
        if [ "${__GLOBAL_OUTPUT_REDIRECTION}"x != ""x ] ; then
          exec 2>&4
          exec 1>&3
          LogInfo "Stopping logging of STDOUT and STDERR to \"${__GLOBAL_OUTPUT_REDIRECTION}\""
          __GLOBAL_OUTPUT_REDIRECTION=
        fi   
        ;;

      * ) 
        THISRC=3
        ;;
    esac
  else
    THISRC=2
  fi

  return ${THISRC}
}

## --------------------------------------
## executeCommand
##
## execute a command
##
## usage: executeCommand command parameter
##
## returns: the RC of the executed command
##
function executeCommand {
  typeset __FUNCTION="executeCommand";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset THISRC=0

  set +e

  LogRuntimeInfo "Executing \"$@\" "  

  eval "$@"
  THISRC=$?
  
  return ${THISRC}
}

## --------------------------------------
## executeCommandAndLog
##
## execute a command and write STDERR and STDOUT to the logfile
##
## usage: executeCommandAndLog command parameter
##
## returns: the RC of the executed command
##
function executeCommandAndLog {
  typeset __FUNCTION="executeCommandAndLog";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  set +e
  typeset THISRC=0

  LogRuntimeInfo "Executing \"$@\" "  

  if [ "${__LOGFILE}"x != ""x -a -f "${__LOGFILE}" ] ; then
    eval "$@" 2>&1 | tee -a "${__LOGFILE}"
    THISRC=$?
  else    
    eval "$@"
    THISRC=$?
  fi

  return ${THISRC}
}

## --------------------------------------
## executeCommandAndLogSTDERR
##
## execute a command and write STDERR to the logfile
##
## usage: executeCommandAndLogSTDERR command parameter
##
## returns: the RC of the executed command
##
function executeCommandAndLogSTDERR {
  typeset __FUNCTION="executeCommandAndLogSTDERR";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  set +e
  typeset THISRC=0

  LogRuntimeInfo "Executing \"$@\" "  >&2

  if [ "${__LOGFILE}"x != ""x -a -f" ${__LOGFILE}" ] ; then
    eval "$@" 2>>${__LOGFILE}
    THISRC=$?
  else    
    eval "$@"
    THISRC=$?
  fi

  return ${THISRC}
}

## --------------------------------------
## UserIsRoot
##
## validate the user id
##
## usage: UserIsRoot
##
## returns: ${__TRUE} - the user is root; else not
##
function UserIsRoot {
  typeset __FUNCTION="UserIsRoot";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  [ "$( id | sed 's/uid=\([0-9]*\)(.*/\1/' )" = 0 ] && return ${__TRUE} || return ${__FALSE}
}


## --------------------------------------
## UserIs
##
## validate the user id
##
## usage: UserIs USERID
##
## where: USERID - userid (e.g oracle)
##
## returns: 0 - the user is this user
##          1 - the user is NOT this user
##          2 - the user does not exist on this machine
##          3 - missing parameter
##
function UserIs {
  typeset __FUNCTION="UserIs";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset THISRC=3
  typeset USERID=""
  
  if [ "$1"x != ""x ] ; then
    THISRC=2
    USERID=$( grep "^$1:" /etc/passwd | cut -d: -f3 )
    if [ "${USERID}"x != ""x ] ; then
      UID="$( id | sed 's/uid=\([0-9]*\)(.*/\1/' )"      
      [ ${UID} = ${USERID} ] && THISRC=0 || THISRC=1   
    fi
  fi

  return ${THISRC}
}

## --------------------------------------
## GetCurrentUID
##
## get the UID of the current user
##
## usage: GetCurrentUID
##
## where: - 
##
## returns: the UID (e.g. 100)
##
function GetCurrentUID {
  typeset __FUNCTION="GetCurrentUID";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  return "$(id | sed 's/uid=\([0-9]*\)(.*/\1/')"
}

## --------------------------------------
## GetUserName
##
## get the name of a user
##
## usage: GetUserName UID
##
## where: UID - userid (e.g 1686)
##
## returns: 0
##          __USERNAME contains the user name or "" if
##           the userid does not exist on this machine
##
function GetUserName {
  typeset __FUNCTION="GetUserName";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  [ "$1"x != ""x ] &&  __USERNAME=$( grep ":$1:" /etc/passwd | cut -d: -f1 )  || __USERNAME=""
  
  return 0
}

## --------------------------------------
## GetUID
##
## get the UID for a username
##
## usage: GetUID username
##
## where: username - user name (e.g nobody)
##
## returns: 0
##          __USER_ID contains the UID or "" if
##          the username does not exist on this machine
##
function GetUID {
  typeset __FUNCTION="GetUID";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  [ "$1"x != ""x ] &&  __USER_ID=$( grep "^$1:" /etc/passwd | cut -d: -f3 ) || __USER_ID=""
  
  return 0
}


# ======================================
 
## --------------------------------------
## LogMsg
##
## print a message to STDOUT and write it also to the logfile
##
## usage: LogMsg message
##
## returns: 0
##
## Notes: Use "- message" to suppress the date stamp
##        Use "-" to print a complete blank line
##
function LogMsg {
  typeset __FUNCTION="LogMsg";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  if [ "$1"x = "-"x ] ; then
    shift
    typeset THISMSG="$*"
  elif [ "${__NO_TIME_STAMPS}"x = "${__TRUE}"x ] ; then
    typeset THISMSG="$*"
  else
    typeset THISMSG="[$(date +"%d.%m.%Y %H:%M:%S")] $*"
  fi
  
  [  ${__QUIET_MODE} -ne ${__TRUE} ] && echo "${THISMSG} "
  [ "${__LOGFILE}"x != ""x ] && [ -f "${__LOGFILE}" ] &&  echo "${THISMSG}" >>${__LOGFILE} 
  
  return 0
}


## --------------------------------------
## LogOnly
##
## write a message to the logfile
##
## usage: LogOnly message
##
## returns: 0
##
function LogOnly {
  typeset __FUNCTION="LogOnly";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset THISMSG="[$(date +"%d.%m.%Y %H:%M:%S")] $*"

  [ "${__LOGFILE}"x != ""x ] && [ -f "${__LOGFILE}" ] &&  echo "${THISMSG}" >>${__LOGFILE} 
  
  return 0
}

## --------------------------------------
## LogInfo
##
## print a message to STDOUT and write it also to the logfile 
## only if in verbose mode
##
## usage: LogInfo [loglevel] message
##
## returns: 0
##
## Notes: Output goes to STDERR, default loglevel is 0
##
function LogInfo {
  typeset __FUNCTION="LogInfo";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

#  [ ${__VERBOSE_MODE} -eq ${__TRUE} ] && LogMsg "INFO: $*"

  typeset THISLEVEL=0
  
  if [ ${__VERBOSE_MODE} -eq ${__TRUE} ] ; then
    if [ $# -gt 1 ] ; then
      isNumber $1 
      if [ $? -eq ${__TRUE} ] ; then
        THISLEVEL=$1
        shift
      fi
    fi      
    [ ${__VERBOSE_LEVEL} -gt ${THISLEVEL} ]  && LogMsg "INFO: $*" >&2
  fi  
  return 0
  }

# internal sub routine for info messages from the runtime system
#
#
function LogRuntimeInfo {
  typeset __FUNCTION="LogRuntimeInfo";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}
  LogInfo "${__RT_VERBOSE_LEVEL}" "$*"
  return 0
}

# internal sub routine for header messages
#
#
function LogHeader {
  [ "${__NO_HEADERS}"x != "${__TRUE}"x ] && LogMsg "$*"
  return 0
}

## --------------------------------------
## LogWarning
##
## print a warning to STDERR and write it also to the logfile
##
## usage: LogWarning message
##
## returns: 0
##
## Notes: Output goes to STDERR
##
function LogWarning {
  typeset __FUNCTION="LogWarning";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  LogMsg "WARNING: $*" >&2
  (( __NO_OF_WARNINGS = __NO_OF_WARNINGS +1 ))
  __LIST_OF_WARNINGS="${__LIST_OF_WARNINGS}
WARNING: $*"  
  return 0
}

## --------------------------------------
## LogError
##
## print an error message to STDERR and write it also to the logfile
##
## usage: LogError message
##
## returns: 0
##
## Notes: Output goes to STDERR
##
function LogError {
  typeset __FUNCTION="LogError";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  LogMsg "ERROR: $*" >&2

  (( __NO_OF_ERRORS=__NO_OF_ERRORS + 1 ))  
  __LIST_OF_ERRORS="${__LIST_OF_ERRORS}
ERROR: $*"  
  return 0
}


## ---------------------------------------
## BackupFileIfNecessary
##
## create a backup of a file if ${__OVERWRITE_MODE} is set to ${__FALSE}
##
## usage: BackupFileIfNecessary [file1} ... {filen}
##
## returns: 0 - done; else error
##
function BackupFileIfNecessary {
  typeset __FUNCTION="BackupFileIfNecessary";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

 [ "${BACKUP_EXTENSION}"x = ""x ] && BACKUP_EXTENSION=".$$"
 
 typeset FILES_TO_BACKUP="$*"
 typeset CURFILE=""
 typeset CUR_BKP_FILE=""
 typeset THISRC=0
  
 if [ ${__OVERWRITE_MODE} -eq ${__FALSE} ] ; then
   for CURFILE in ${FILES_TO_BACKUP} ; do         
     [ ! -f "${CURFILE}" ] && continue

     CUR_BKP_FILE="${CURFILE}${BACKUP_EXTENSION}"
     LogMsg "Creating a backup of \"${CURFILE}\" in \"${CUR_BKP_FILE}\" ..."
     cp "${CURFILE}" "${CUR_BKP_FILE}"
     THISRC=$?
     if [ ${THISRC} -ne 0 ] ; then
       LogError "Error creating the backup of the file \"${CURFILE}\""
       break
     fi
   done
 fi
 
 return ${THISRC}
}  
 
## ---------------------------------------
## CopyDirectory
##
## copy a directory 
##
## usage: CopyDirectory sourcedir targetDir
##
## returns:  0 - done; 
##           else error
##
function CopyDirectory {
  typeset __FUNCTION="CopyDirectory";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset THISRC=1
  if [ "$1"x != ""x -a "$2"x != ""x  ] ; then
     if [ -d "$1" -a -d "$2" ] ; then
        LogMsg "Copying all files from \"$1\" to \"$2\" ..."
        cd "$1"
        find . -depth -print | cpio -pdumv "$2"
        THISRC=$?
        cd "${OLDPWD}"
     fi
  fi

  return ${THISRC}
}


## --------------------------------------
## AskUser
##
## Ask the user (or use defaults depending on the parameter -n and -y)
##
## Usage: AskUser "message" 
##        
## returns: ${__TRUE} - user input is yes
##          ${__FALSE} - user input is no
##          USER_INPUT contains the user input
##
## Notes: "all" is interpreted as yes for this and all other questions
##        "none" is interpreted as no for this and all other questions
##
## If __NOECHO is ${__TRUE} the user input is not written to STDOUT
## __NOECHO is set to ${__FALSE} again in this function
##
## If __USE_TTY is ${__TRUE} the prompt is written to /dev/tty and the 
## user input is read from /dev/tty . This is useful if STDOUT is redirected 
## to a file.
##
function AskUser {
  typeset __FUNCTION="AskUser";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset THISRC=""

  if [ "${__USE_TTY}"x = "${__TRUE}"x ] ; then
    typeset mySTDIN="</dev/tty"
    typeset mySTDOUT=">/dev/tty"
  else
    typeset mySTDIN=""
    typeset mySTDOUT=""
  fi
  
  case ${__USER_RESPONSE_IS} in 
     
   "y" ) USER_INPUT="y" ; THISRC=${__TRUE} 
         ;;

   "n" ) USER_INPUT="n" ; THISRC=${__FALSE} 
         ;;
   
     * ) [ $# -ne 0 ] && eval LogMsg "-" "\"$* \c\"" ${mySTDOUT}
          if [ ${__NOECHO} = ${__TRUE} ] ; then
            __STTY_SETTINGS="$( stty -g )"
            stty -echo
          fi
          eval read USER_INPUT ${mySTDIN}
          if [ ${__NOECHO} = ${__TRUE} ] ; then
            stty ${__STTY_SETTINGS}
            __STTY_SETTINGS=""
          fi

         case ${USER_INPUT} in

           "y" | "Y" ) THISRC=${__TRUE}  ;;

           "n" | "N" ) THISRC=${__FALSE} ;;

           "all" ) __USER_RESPONSE_IS="y"  ; THISRC=${__TRUE}  ;;

           "none" )  __USER_RESPONSE_IS="n" ;  THISRC=${__FALSE} ;;

           * )  THISRC=${__FALSE} ;;

        esac
        ;;
  esac  

  __NOECHO=${__FALSE}
  return ${THISRC}
}

## --------------------------------------
## GetKeystroke
##
## read one key from STDIN
##
## Usage: GetKeystroke "message" 
##        
## returns: 0
##          USER_INPUT contains the user input
##          
function GetKeystroke {
  typeset __FUNCTION="GetKeystroke";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  trap "" 2 3
  [ $# -ne 0 ] && LogMsg "${THISMSG}"

  __STTY_SETTINGS="$( stty -g )"

  stty -echo raw
  USER_INPUT=$( dd count=1 2> /dev/null )

  stty ${__STTY_SETTINGS}
  __STTY_SETTINGS=""

  trap 2 3
  
  return 0
} 

## --------------------------------------
## RebootIfNecessary
##
## Check if a reboot is necessary
##
## Usage: RebootIfNecessary
##
## Notes
##   The routine asks the user if neither the parameter -y nor the 
##   parameter -n is used
##   Before using this routine uncomment the reboot command!
##
function RebootIfNecessary {
  typeset __FUNCTION="RebootIfNecessary";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  if [ ${__REBOOT_REQUIRED} -eq 0 ] ; then
    LogMsg "The changes made to the system require a reboot"

    AskUser "Do you want to reboot now (y/n, default is NO)?"
    if [ $? -eq ${__TRUE} ] ; then
      LogMsg "Rebooting now ..."
      echo "???" reboot ${__REBOOT_PARAMETER}
    fi
  fi
  
  return 0
}

## ---------------------------------------
## die
##
## print a message and end the program
##
## usage: die returncode {message}
##
## returns: $1 (if it returns)
##
## Notes: 
##
## This routine 
##     - calls cleanup
##     - prints an error message if any (if returncode is not zero)
##       or the message if any (if returncode is zero)
##     - prints all warning messages again if ${__PRINT_LIST_OF_WARNING_MSGS} 
##       is ${__TRUE}
##     - prints all error messages again if ${__PRINT_LIST_OF_ERROR_MSGS} 
##       is ${__TRUE}
##     - prints a program end message and the program return code
## and
##     - and ends the program
##
## If the variable ${__FORCE} is ${__TRUE} and the return code is NOT zero
## die() will only print the error message and return
##
function die {
  typeset __FUNCTION="die";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  [ "${__TRAP_SIGNAL}"x != ""x ] &&  LogRuntimeInfo "__TRAP_SIGNAL is \"${__TRAP_SIGNAL}\""
  
  typeset THISRC=$1
  [ $# -ne 0 ] && shift
  
  if [ "$*"x != ""x ] ; then
    [ ${THISRC} = 0 ] && LogMsg "$*" || LogError "$*"
  fi

  [ ${__FORCE} = ${__TRUE} -a ${THISRC} != 0 ] && return

  cleanup
  
  if [ "${__NO_OF_WARNINGS}" != "0" -a ${__PRINT_LIST_OF_WARNINGS_MSGS} -eq ${__TRUE} ] ; then
    LogMsg "*** CAUTION: One or more WARNINGS found ***"
    LogMsg "*** please check the logfile ***"
    
    LogMsg "Summary of warnings:
${__LIST_OF_WARNINGS}
"
  fi    

  if [ "${__NO_OF_ERRORS}" != "0" -a ${__PRINT_LIST_OF_ERROR_MSGS} -eq ${__TRUE} ] ; then
    LogMsg "*** CAUTION: One or more ERRORS found ***"
    LogMsg "*** please check the logfile ***"

    LogMsg "Summary of error messages
${__LIST_OF_ERRORS}
"
  fi    

  [[ -n "${__LOGFILE}" ]] && LogHeader "The log file used was \"${__LOGFILE}\" "
  __QUIET_MODE=${__FALSE}
  LogHeader "${__SCRIPTNAME} ended on $( date )."
  LogHeader "The RC is ${THISRC}."
  
  __EXIT_VIA_DIE=${__TRUE} 

  StartStop_LogAll_to_logfile "stop" 

  RebootIfNecessary
  
  exit ${THISRC}
}


## ---------------------------------------
## includeScript
##
## include a script via . [scriptname]
##
## usage: includeScript [scriptname]
##
## returns: 0
##
## notes: 
##
function includeScript {
  typeset __FUNCTION="includeScript";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  if [ $# -ne 0 ] ; then
   
    LogRuntimeInfo "Including the script \"$*\" ..."

# set the variable for the TRAP handlers
    [ ! -f "$1" ] && die 247 "Include script \"$1\" not found"
    __INCLUDE_SCRIPT_RUNNING="$1"
  
# include the script
    . $*

# reset the variable for the TRAP handlers  
    __INCLUDE_SCRIPT_RUNNING=""

  fi
}

# ======================================

## 
## ##### defined internal sub routines (do NOT use; these routines are called 
##       by the runtime system!)
##

# --------------------------------------
## CreateLockFile
#
# Create the lock file (which is really a symbolic link) if possible
#
# usage: CreateLockFile
#
# returns: 0 - lock created
#          1 - lock already exist or error creating the lock
#
# Note: Use a symbolic link because this is always a atomic operation
#
function CreateLockFile {
  typeset __FUNCTION="CreateLockFile";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset LN_RC=""

  ln -s  "$0" "${__LOCKFILE}" 2>/dev/null
  LN_RC=$?
      
  if [ ${LN_RC} = 0 ] ; then
    __LOCKFILE_CREATED=${__TRUE}
    return 0 
  else
    return 1
  fi
}

# --------------------------------------
## RemoveLockFile
#
# Remove the lock file if possible
#
# usage: RemoveLockFile
#
# returns: 0 - lock file removed
#          1 - lock file does not exist
#          2 - error removing the lock file
#
function RemoveLockFile {
  typeset __FUNCTION="RemoveLockFile";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  [ ! -L "${__LOCKFILE}" ] && return 1
  if [ ${__LOCKFILE_CREATED} -eq ${__TRUE} ] ; then
    rm "${__LOCKFILE}" 1>/dev/null 2>/dev/null
    [ $? -eq 0 ] && return 0
  fi  
  return 2
}

# ======================================

# --------------------------------------
## CreateTemporaryFiles
#
# create the temporary files
#
# usage: CreateTemporaryFiles
#
# returns: 0
#
# notes: 
#  The variables with the tempfiles are called
#  __TEMPFILE1, __TEMPFILE2, ..., __TEMPFILE#
#
function CreateTemporaryFiles {
  typeset __FUNCTION="CreateTemporaryFiles";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset CURFILE=
  
  typeset i=1

  __TEMPFILE_CREATED=${__TRUE}

  LogRuntimeInfo "Creating the temporary files  ..."

  while [ ${i} -le ${__NO_OF_TEMPFILES} ]  ; do   
    eval __TEMPFILE${i}="${__TEMPDIR}/${__SCRIPTNAME}.$$.TEMP${i}"
    eval CURFILE="\$__TEMPFILE${i}"

    LogRuntimeInfo "Creating the temporary file \"${CURFILE}\"; the variable is \"\${TEMPFILE${i}}" 

    echo >"${CURFILE}" || return $?
    
    eval __LIST_OF_TMP_FILES=\"${__LIST_OF_TMP_FILES} \${__TEMPFILE${i}}\"
    (( i = i +1 ))
  done

  return 0
}

# ======================================


# ======================================

##
## ---------------------------------------
## cleanup
##
## house keeping at program end
##
## usage: [called by the runtime system]
##
## returns: 0
##
## notes: 
##  execution order is
##    - call exit routines from ${__EXITROUTINES}
##    - remove files from ${__LIST_OF_TMP_FILES}
##    - umount mount points ${__LIST_OF_TMP_MOUNTS}
##    - remove directories ${__LIST_OF_TMP_DIRS}
##    - call finish routines from ${__FINISHROUTINES}
##
function cleanup {
  typeset __FUNCTION="cleanup";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset EXIT_ROUTINE=
  typeset OLDPWD="$( pwd )"

  cd /tmp

# reset tty settings if necessary
  if [ "${__STTY_SETTINGS}"x != ""x ] ; then
    stty ${__STTY_SETTINGS}
    __STTY_SETTINGS=""
  fi
  
# call the defined exit routines
  LogRuntimeInfo "Executing the exit routines \"${__EXITROUTINES}\" ..."
  if [ "${__EXITROUTINES}"x !=  ""x ] ; then
    for EXIT_ROUTINE in ${__EXITROUTINES} ; do
      LogRuntimeInfo "Now calling the exit routine \"${EXIT_ROUTINE}\" ..."
      eval ${EXIT_ROUTINE}
    done
  fi

# remove temporary files
  LogRuntimeInfo "Removing temporary files ..."
  for CURENTRY in ${__LIST_OF_TMP_FILES} ; do
    LogRuntimeInfo "Removing the file \"${CURENTRY}\" ..."
    if [ -f "${CURENTRY}" ] ; then
      rm "${CURENTRY}" 
      [ $? -ne 0 ] && LogWarning "Error removing the file \"${CURENTRY}\" "
    fi
  done
 
# remove temporary mounts
  LogRuntimeInfo "Removing temporary mounts ..."
  typeset CURENTRY
  for CURENTRY in ${__LIST_OF_TMP_MOUNTS} ; do
    mount | grep "^${CURENTRY} " 1>/dev/null 2>/dev/null
    if [ $? -eq 0 ] ; then
      LogRuntimeInfo "Umounting \"${CURENTRY}\" ..."
      umount "${CURENTRY}" 
      [ $? -ne 0 ] && LogWarning "Error umounting \"${CURENTRY}\" "
    fi
  done

# remove temporary directories
  LogRuntimeInfo "Removing temporary directories ..."
  for CURENTRY in ${__LIST_OF_TMP_DIRS} ; do
    LogRuntimeInfo "Removing the directory \"${CURENTRY}\" ..."
    if [ -d "${CURENTRY}" ] ; then
      rm -r "${CURENTRY}" 2>/dev/null
      [ $? -ne 0 ] && LogWarning "Error removing the directory \"${CURENTRY}\" "
    fi
  done

# call the defined finish routines
  LogRuntimeInfo "Executing the finish routines \"${__FINISHROUTINES}\" ..."
  if [ "${__FINISHROUTINES}"x !=  ""x ] ; then
    for FINISH_ROUTINE in ${__FINISHROUTINES} ; do
      LogRuntimeInfo "Now calling the finish routine \"${FINISH_ROUTINE}\" ..."
      eval ${FINISH_ROUTINE}
    done
  fi

  [ -d "${OLDPWD}" ] && cd "${OLDPWD}"
  
  return 0
}



## 
## ##### defined trap handler (you may change them)
##


## ---------------------------------------
## GENERAL_SIGNAL_HANDLER
##
## general trap handler 
##
## usage: called automatically;
##        parameter: $1 = signal number
##                   $2 = LineNumber
##                   $3 = function name
##
## returns: -
##
function GENERAL_SIGNAL_HANDLER {
  typeset __RC=$?
  __TRAP_SIGNAL=$1
  typeset __LINENO=$2  
  typeset INTERRUPTED_FUNCTION=$3
  
  typeset __FUNCTION="GENERAL_SIGNAL_HANDLER";    ${__DEBUG_CODE}

  if [ "${__EXIT_VIA_DIE}"x != "${__TRUE}"x -a ${__TRAP_SIGNAL} != "exit" ] ; then
    LogRuntimeInfo "Trap \"${__TRAP_SIGNAL}\" caught"
      
    [ "${__INCLUDE_SCRIPT_RUNNING}"x != ""x ] && LogMsg "Trap occurred inside of the include script \"${__INCLUDE_SCRIPT_RUNNING}\" "
  
    LogRuntimeInfo "Signal ${__TRAP_SIGNAL} received: Line: ${__LINENO} in function: ${INTERRUPTED_FUNCTION}"
  fi
  
  case ${__TRAP_SIGNAL} in 

    1 )
        LogWarning "HUP signal received"

        InvertSwitch __VERBOSE_MODE
        LogMsg "Switching verbose mode to $( ConvertToYesNo ${__VERBOSE_MODE} )"
        ;;

    2 )
        if [ ${__USER_BREAK_ALLOWED} -eq ${__TRUE} ] ; then
          die 252 "Script aborted by the user via signal BREAK (CTRL-C)" 
        else
          LogRuntimeInfo "Break signal (CTRL-C) received and ignored (Break is disabled)"
        fi
        ;;

    3 )
        die 251 "QUIT signal received" 
        ;;

   15 )
        die 253 "Script aborted by the external signal TERM" 
        ;;

   "ERR" )
        LogMsg "A command ended with an error; the RC is ${__RC}"
        ;;

   "exit" | 0 )
        if [ "${__EXIT_VIA_DIE}"x != "${__TRUE}"x ] ; then
          LogError "EXIT signal received; the RC is ${__RC}"
          [ "${__INCLUDE_SCRIPT_RUNNING}"x != ""x ] && LogMsg "exit occurred inside of the include script \"${__INCLUDE_SCRIPT_RUNNING}\" "
          LogWarning "You should use the function \"die\" to end the program"
        fi    
        return
        ;;
       
    * ) die 254 "Unknown signal caught: ${__TRAP_SIGNAL}"
        ;;

  esac
}


# ======================================


## ---------------------------------------
## DebugHandler
##
## handler for single step mode
##
## usage: called automatically
##
## returns: the RC of the previous executed command
##
function DebugHandler {
  typeset __FUNCTION="DebugHandler";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  [ "${__DEBUG_MODE}" -ne ${__TRUE} ] && return ${__LAST_RC}

  __STTY_SETTINGS="$( stty -g )"
#  stty erase 
  
  typeset __THIS_PID=$$

  typeset -i i=0
  typeset -i j=0

  if [ "${__USE_COLORS}"x = "${__TRUE}"x ] ; then
    typeset __LINE_COLOR="\033[0;36m\033[44m"
    typeset __CUR_LINE_COLOR="\033[0;34m\033[46m"
    typeset __DEBUG_MSG_COLOR="\033[0;31m\033[48m"
    typeset __COLOR_OFF="\033[0;m"   
  else
    typeset __LINE_COLOR=""
    typeset __CUR_LINE_COLOR=""
    typeset __DEBUG_MSG_COLOR=""
    typeset __COLOR_OFF=""
  fi

  COLUMNS=80
  typeset RESIZE_BINARY="$( whence resize )"
  [ "${RESIZE_BINARY}"x = ""x ] && RESIZE_BINARY="/usr/openwin/bin/resize"
  [ -x "${RESIZE_BINARY}" ] && eval $( ${RESIZE_BINARY} ) 
  (( COLUMNS = $COLUMNS - 1 ))
  eval "typeset -L${COLUMNS} LINE_VAR"
  
#  typeset  -L80 __LINE_VAR=""
  typeset __USERINPUT=""

  set -o emacs
  
  alias __A=$(print "\020")    # up arrow    -> Ctrl-P (previous cmd)
  alias __B=$(print "\016")    # down arrow  -> Ctrl-N (next cmd)
  alias __C=$(print "\006")    # right arrow -> Ctrl-F (move forward 1 char)
  alias __D=$(print "\002")    # left arrow  -> Ctrl-B (move backward 1 char)
  alias __H=$(print "\001")    # home        -> Ctrl-A (go to beginning of line)
  alias __P=$(print "\004")    # delete      -> Ctrl-D (delete char under cursor)
  alias __@=" "
  alias __Q=$(print "\005")    # end         -> Ctrl-E (go to end of line)
  alias __Z=$(print "\017")    # end         -> Ctrl-O (operate)

  export HISTFILE="${__DEBUG_HISTFILE}"
  
# check for the break points
  if [ "${__BREAKPOINT_LINE}"x != "0"x ] ; then
    if [ "${__BREAKPOINT_LINE}" -ge "${__LINENO}" ] ; then
      __LINE_VAR="*** DEBUG: Break point at line ${__LINENO} found"
      print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"
      __BREAKPOINT_LINE=0
    else
      return ${__LAST_RC}
    fi
  fi

  if [ "${__STEP_COUNT}"x != "0"x ] ; then
    __STEP_COUNT=$(( __STEP_COUNT - 1 ))
    if [  "${__STEP_COUNT}"x = "0"x  ] ; then
      __LINE_VAR="*** DEBUG: Break point at line ${__LINENO} found"
      print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"
    else
      return ${__LAST_RC}
    fi
  fi


# read the script into an array (only once!)
  if [ ${__SCRIPT_ARRAY[0]} = 0 ] ; then
    typeset oIFS=$IFS
    IFS="\n"

    i=1

    while read -r __SCRIPT_ARRAY[$i] ; do
      i=$(( i+1 ))
    done <$0

    __SCRIPT_ARRAY[0]=$i

    IFS=$oIFS
  fi

# define the variables for the output 

  i=${__SCRIPT_ARRAY[0]}
  eval "typeset -R${#i} NUM_VAR"  
  j=$(( ${COLUMNS} - ${#i} -1 ))
#  eval "typeset -L${j} __SRCLINE_VAR"  
  eval "typeset -L${COLUMNS} __SRCLINE_VAR"
  
  if [ "${__TRACE_COUNT}"x != "0"x ] ; then
    __SRCLINE_VAR="${NUM_VAR}>>> ${__SCRIPT_ARRAY[${__LINENO}]}"
    print -u2 "${__CUR_LINE_COLOR}${__SRCLINE_VAR}"
    __TRACE_COUNT=$(( ${__TRACE_COUNT}-1 ))
    print "${__COLOR_OFF}"
    return ${__LAST_RC}
  fi 

# write the script to a file  
#  i=1
#  while [ i -lt ${__SCRIPT_ARRAY[0]} ] ; do 
#     echo "$i ${__SCRIPT_ARRAY[$i]}" >>./test.out
#     i=$(( i+1 ))
#  done
    
  __LINE_VAR=""   
  print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"

  __LINE_VAR="*** DEBUG: Executed line: ${__LINENO}"
  print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"
  __LINE_VAR="*** DEBUG: Line Context:"
  print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"

  [ ${__LINENO} -gt 5 ] && i=$(( ${__LINENO}-5 )) || i=1
  typeset CUR_SRC_WIN_START=$i
  j=$(( ${__LINENO}+5 ))
  [ ${j} -gt ${__SCRIPT_ARRAY[0]} ] && j=${__SCRIPT_ARRAY[0]}

# write the context of the line just executed   
  while [ i -lt j ] ; do
    NUM_VAR=$i
    if [ $i -eq ${__LINENO} ] ; then
      __SRCLINE_VAR="${NUM_VAR}>>> ${__SCRIPT_ARRAY[$i]}"
      print -u2 "${__CUR_LINE_COLOR}${__SRCLINE_VAR}${__COLOR_OFF} "
    else
      __SRCLINE_VAR="${NUM_VAR}    ${__SCRIPT_ARRAY[$i]}"
      print -u2 "${__LINE_COLOR}${__SRCLINE_VAR}${__COLOR_OFF} "
    fi
      i=$(( i+1 ))
  done   
  print "${__COLOR_OFF}"
  
# read the user input
#
  __LINE_VAR="*** DEBUG: \$\$ is ${__THIS_PID}; \$? is ${__LAST_RC}; \$! is ${__LAST_BG_RC}"
  print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"
  __LINE_VAR="*** DEBUG: Enter a command to execute or <enter> to execute the next command:"
  print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"

  while [ 1 = 1 ] ; do
    echo $COLUMNS
    echo $LINE
    print -u2 -n  "${__DEBUG_MSG_COLOR}DEBUG>>> "
    read -s __USERINPUT __USERPARMS __USERVALUE __USERVALUE2
  
    case ${__USERINPUT} in 

      "help" | "?" ) __LINE_VAR="*** DEBUG:Known commands"
           print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"
cat 1>&2 <<EOT

  help                      - print this text
  trace count               - execute count lines
  trace off                 - turn single mode off
  trace at lineNo           - suspend single step until line lineNo
  trace not lineNumber      - suspend single step for lineNumber statements
  show lineNo [count]       - show count (def.: 10) lines after line lineNo
  exit [returncode]         - exit the program with RC returnCode (def.: 1)
  <return>                  - execute next statement (single step)
  everything else           - execute the command 

EOT
           ;; 
   
   
      "" ) break 
           ;;
           
      "trace"  ) :
          case ${__USERPARMS}  in 

            "off" )
              __LINE_VAR="*** DEBUG: Turning single step mode off"
              print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"
              __DEBUG_MODE=${__FALSE} 
              break
              ;;
      
            "at" )
              if [ "${__USERVALUE}"x = ""x ] ; then
                __LINE_VAR="*** DEBUG: value missing"
                print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"
                continue
              fi

              isNumber "${__USERVALUE}" 2>/dev/null
              if [ $? -ne 0 ] ; then
                __LINE_VAR="*** DEBUG: \"${__USERVALUE}\" is not a number"
                print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"
                continue
              fi         

              __LINE_VAR="*** DEBUG: Suspending single step until line ${__USERVALUE}"
              print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"
              __BREAKPOINT_LINE=${__USERVALUE}      
              break
              ;;

            "not" )
              if [ "${__USERVALUE}"x = ""x ] ; then
                __LINE_VAR="*** DEBUG: value missing"
                print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"
                continue
              fi

              isNumber "${__USERVALUE}" 2>/dev/null
              if [ $? -ne 0 ] ; then
                __LINE_VAR="*** DEBUG: \"${__USERVALUE}\" is not a number"
                print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"
                continue
              fi         

              __LINE_VAR="*** DEBUG: Suspending single step for the next ${__USERVALUE} statements"
              print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"
              __STEP_COUNT=${__USERVALUE}      
              break
              ;;


            * )
              isNumber "${__USERPARMS}" 2>/dev/null
              if [ $? -eq 0 ] ; then
                __TRACE_COUNT=${__USERPARMS}
                __LINE_VAR="*** DEBUG: Executing \"${__USERPARMS}\" lines"
                print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"
                break
              else
                __LINE_VAR="*** DEBUG: unknown trace option \"${__USERPARMS}\" "
                print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"    
              fi
              ;;
      
          esac
          ;;   

      "show" )      
           [ "${__USERPARMS}"x = ""x ] && __USERPARMS=${CUR_SRC_WIN_START}

           isNumber "${__USERPARMS}" 2>/dev/null
           if [ $? -ne 0 ] ; then
             __LINE_VAR="*** DEBUG: \"${__USERPARMS}\" is not a number"
             print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"
             continue
           fi         

           if [ "${__USERPARMS}" -lt 1 ] ; then
             __LINE_VAR="*** DEBUG: \"${__USERPARMS}\" is out of range"
             print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"
             continue
           fi         

           if [ "${__USERPARMS}" -gt ${__SCRIPT_ARRAY[0]} ] ; then
             __LINE_VAR="*** DEBUG: \"${__USERPARMS}\" is out of range (last line is ${__SCRIPT_ARRAY[0]})"
             print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"    
             continue
           fi

           i=${__USERPARMS}

           if [ "${__USERVALUE}"x != ""x ] ; then
             isNumber "${__USERVALUE}" 2>/dev/null
             if [ $? -ne 0 ] ; then
               __LINE_VAR="*** DEBUG: \"${__USERVALUE}\" is not a number"
               print -u2 "${__DEBUG_MSG_COLOR}${__LINE_VAR}"
               continue
             fi         
             j=$(( ${i}+ ${__USERVALUE} -1 )) 
           else
             j=$(( ${i}+9 ))   
           fi

           [ ${j} -gt ${__SCRIPT_ARRAY[0]} ] && j=${__SCRIPT_ARRAY[0]}

           while [ i -le j ] ; do
             NUM_VAR=$i
             if [ $i -eq ${__LINENO} ] ; then
               __SRCLINE_VAR=">>> ${__SCRIPT_ARRAY[$i]}"
               print -u2 "${__CUR_LINE_COLOR}${NUM_VAR} ${__SRCLINE_VAR}"
             else
               __SRCLINE_VAR="    ${__SCRIPT_ARRAY[$i]}"
               print -u2 "${__LINE_COLOR}${NUM_VAR} ${__SRCLINE_VAR}"
             fi 
             i=$(( i+1 ))
           done      
     
           ;;
   
      "exit" | "quit" )  :
           print "${__COLOR_OFF}"
           [ "${__USERPARMS}"x = ""x ] && die 252 "Program aborted by the user"
           die ${__USERPARMS} 
           ;;

      * ) executeCommand "${__USERINPUT}" "${__USERPARMS}" "${__USERVALUE}" "${__USERVALUE2}"
            ;;
    esac
  done
  print "${__COLOR_OFF}"

  return ${__LAST_RC}
}



## ---------------------------------------
## InitScript
##
## init the script runtime 
##
## usage: [called by the runtime system]
##
## returns: 0
##
function InitScript {    
  typeset __FUNCTION="InitScript";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

# use a temporary log file until we know the real log file
  __TEMPFILE_CREATED=${__FALSE}
  __MAIN_LOGFILE=${__LOGFILE}
  
  __LOGFILE="/tmp/${__SCRIPTNAME}.$$.TEMP"
  echo >${__LOGFILE}

  LogHeader "${__SCRIPTNAME} started on $( date ) "

  LogRuntimeInfo "Script template used is \"${__SCRIPT_TEMPLATE_VERSION}\" ."

  __WRITE_CONFIG_AND_EXIT=${__FALSE} 
  
# init the variables
  eval "${__CONFIG_PARAMETER}"

# read the config file
  ReadConfigFile

  return 0
}


## ---------------------------------------
## SetEnvironment
##
## set and check the environment
##
## usage: [called by the runtime system]
##
## returns: 0
##
function SetEnvironment {
  typeset __FUNCTION="SetEnvironment";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}
 
# copy the temporary log file to the real log file

  if [ "${NEW_LOGFILE}"x = "nul"x ] ; then
    LogHeader "Running without a log file"
    __MAIN_LOGFILE=""
# delete the temporary logfile   
    rm "${__LOGFILE}" 2>/dev/null
    __LOGFILE=""
  else
    [ "${NEW_LOGFILE}"x != ""x ] && __MAIN_LOGFILE="${NEW_LOGFILE}"
    LogRuntimeInfo "Initializing the log file\"${__MAIN_LOGFILE}\" "

    touch "${__MAIN_LOGFILE}" 2>/dev/null
    cat "${__LOGFILE}" >>${__MAIN_LOGFILE} 2>/dev/null
    if [ $? -ne 0 ]   ; then
      LogWarning "Error writing to the logfile \"${__MAIN_LOGFILE}\"."
      LogWarning "Using the log file \"${__LOGFILE}\" "
    else
      rm "${__LOGFILE}" 2>/dev/null
      __LOGFILE="${__MAIN_LOGFILE}"
    fi
    LogHeader "Using the log file \"${__LOGFILE}\" "
  fi

  if [ "${__REQUIRED_OS}"x != ""x ] ; then
    pos " ${__OS} " " ${__REQUIRED_OS} " && \
      die 238 "This script can not run on this operating system (${__OS}); known Operating systems are \"${__REQUIRED_OS}\""
  fi

  if [ "${__REQUIRED_OS_VERSION}"x != ""x ] ; then

    LogRuntimeInfo "Current OS version is \"${__OS_VERSION}\"; required OS version is \"${__REQUIRED_OS_VERSION}\""
    
    __OS_VERSION_OKAY=${__TRUE}
    
    __CUR_MAJOR_VER="${__OS_VERSION%.*}"
    __CUR_MINOR_VER="${__OS_VERSION#*.}"
  
    __REQ_MAJOR_VER="${__REQUIRED_OS_VERSION%.*}"
    __REQ_MINOR_VER="${__REQUIRED_OS_VERSION#*.}"

    [ "${__CUR_MAJOR_VER}" -lt "${__REQ_MAJOR_VER}" ] && __OS_VERSION_OKAY=${__FALSE}
    [ "${__CUR_MAJOR_VER}" -eq "${__REQ_MAJOR_VER}"  -a "${__CUR_MINOR_VER}" -lt "${__REQ_MINOR_VER}" ] && __OS_VERSION_OKAY=${__FALSE}
    
     [ ${__OS_VERSION_OKAY} = ${__FALSE} ] && die 248 "Unsupported OS Version: ${__OS_VERSION}; necessary OS version is ${__REQUIRED_OS_VERSION}"
      
  fi

  if [ "${__REQUIRED_MACHINE_PLATFORM}"x != ""x ] ; then
    pos " ${__MACHINE_PLATFORM} " " ${__REQUIRED_MACHINE_PLATFORM} " && \
      die 245 "This script can not run on this platform (${__MACHINE_PLATFORM}); necessary platforms are \"${__REQUIRED_MACHINE_PLATFORM}\""
  fi

  if [ "${__REQUIRED_MACHINE_CLASS}"x != ""x ] ; then
    pos " ${__MACHINE_CLASS} " " ${__REQUIRED_MACHINE_CLASS} " && \
      die 244 "This script can not run on this machine class (${__MACHINE_CLASS}); necessary machine classes are \"${__REQUIRED_MACHINE_CLASS}\""
  fi

  if [ "${__REQUIRED_MACHINE_ARC}"x != ""x ] ; then
    pos " ${__MACHINE_ARC} " " ${__REQUIRED_MACHINE_ARC} " && \
      die 243 "This script can not run on this machine architecture (${__MACHINE_ARC}); necessary machine classes are \"${__REQUIRED_MACHINE_ARC}\""
  fi

  if  [ "${__ZONENAME}"x != ""x -a "${__OS}"x = "SunOS"x ] ; then
    case "${__REQUIRED_ZONES}" in 

     "global" ) 
       [ "${__ZONENAME}"x != "global"x ] && \
         die 239 "This script must run in the global zone; the current zone is \"${__ZONENAME}\""
       ;;

     "non-global" | "local" ) 
       [ "${__ZONENAME}"x = "global"x ] && \
         die 239 "This script can not run in the global zone"
       ;;

     "" ) :
       ;;
   
     * ) 
       pos " ${__ZONENAME} " " ${__REQUIRED_ZONES} " && \
         die 239 "This script must run in one of the zones \"${__REQUIRED_ZONES}\"; the current zone is \"${__ZONENAME}\" "
       ;;
       
    esac

  fi
    
  if [ ${__MUST_BE_ROOT} -eq ${__TRUE} ] ; then  
    UserIsRoot || die 249 "You must be root to execute this script" 
  fi

  if [ "${__REQUIRED_USERID}"x != ""x ] ; then
    pos " ${__USERID} "  " ${__REQUIRED_USERID} " && \
      die 242 "This script can only be executed by one of the users: ${__REQUIRED_USERID}"
  fi
        
  if [ ${__ONLY_ONCE} -eq ${__TRUE} ] ; then
    CreateLockFile
    if [ $? -ne 0 ] ; then
      cat >&2  <<EOF

  ERROR:

  Either another instance of this script is already running 
  or the last execution of this script crashes.
  In the first case wait until the other instance ends; 
  in the second case delete the lock file 
  
      ${__LOCKFILE} 

  manually and restart the script.

EOF

      die 250
    fi

# remove the lock file at program end
    __EXITROUTINES="${__EXITROUTINES} RemoveLockFile"    
  fi

# __ABSOLUTE_SCRIPTDIR real absolute directory (no link)
  GetProgramDirectory "$0" __ABSOLUTE_SCRIPTDIR
  
# create temporary files
  CreateTemporaryFiles

# check for the parameter -C 
  if [   "${__WRITE_CONFIG_AND_EXIT}" = ${__TRUE} ] ; then
    NEW_CONFIG_FILE="${__CONFIG_FILE}"
    LogMsg "Creating the config file \"${NEW_CONFIG_FILE}\" ..."
    WriteConfigFile "${NEW_CONFIG_FILE}"
    [ $? -ne 0 ] && die 246 "Error writing the config file \"${NEW_CONFIG_FILE}\""
    die 0 "Configfile \"${NEW_CONFIG_FILE}\" written successfully."    
  fi

}

 
## 
## ##### defined sub routines 
##

## --------------------------------------
## CheckParameterCount
##
## check the number of parameters for a function 
##
## usage: CheckParameterCount parametercount "$@"
##
## returns:  ${__TRUE} - the no of parameter is ok
##           ${__FALSE} - the no of parameter is not ok
##          
##
function CheckParameterCount {
  typeset __CALLED_BY="${__FUNCTION}"
   
  typeset __FUNCTION="CheckParameterCount";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset THISRC=${__FALSE}

  typeset __PARAMETER_COUNT=$1
  shift
  
  if [ $# -eq ${__PARAMETER_COUNT} ] ; then
    THISRC=${__TRUE}
  else
    LogError "CheckParameterCount - Function \"${__CALLED_BY}\" called with $# parameters but the function expects ${__PARAMETER_COUNT} parameter"
    if [ $# -ne 0 ] ; then
      LogError "The parameter are:"
      typeset i=1
      while [ $# -ne 0 ] ; do
        LogError "\$$i : \"$1\" "
        (( i = i + 1 ))
        shift
      done
    fi
  fi

  return ${THISRC}
}


## ---------------------------------------
## ShowShortUsage
##
## print the (short) usage help
##
## usage: ShowShortUsage
##
## returns: 0
##
function ShowShortUsage {
  typeset __FUNCTION="ShowShortUsage";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  eval "__SHORT_USAGE_HELP=\"${__SHORT_USAGE_HELP}\""

cat <<EOT
  ${__SCRIPTNAME} ${__SCRIPT_VERSION} - ${__SHORT_DESC}

  Usage: ${__SCRIPTNAME} [-T] [-v|+v] [-q|+q] [-h] [-l logfile|+l] [-y|+y] [-n|+n] 
                    [-D|+D] [-a|+a] [-O|+O] [-f|+f] [-C] [-H] [-S n] [-V] 
${__SHORT_USAGE_HELP}
  
EOT

  return 0
}


## ---------------------------------------
## ShowUsage
##
## print the (long) usage help
##
## usage: ShowUsage
##
## returns: 0
##
function ShowUsage {
  typeset __FUNCTION="ShowUsage";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  eval "__LONG_USAGE_HELP=\"${__LONG_USAGE_HELP}\""

  ShowShortUsage
cat <<EOT

 Note: Use -{switch} or --{longswitch} to turn an option on; 
       use +{switch} or ++{longswitch} to turn an option off

       The long format of the parameter (--parameter/++parameter) is not supported by all ksh implementations
       
       
    Parameter:

      -v|+v - turn verbose mode on/off; current value: $( ConvertToYesNo "${__VERBOSE_MODE}" )
              Long format: --verbose / ++verbose
      -q|+q - turn quiet mode on/off; current value: $( ConvertToYesNo "${__QUIET_MODE}" )
              Long format: --quiet / ++quiet
      -h    - show usage 
              Long format: --help
      -l    - set the logfile 
              current value: ${NEW_LOGFILE:=${__DEF_LOGFILE}}
              Long format: --logfile      
      +l    - do not write a logfile
              Long format: ++logfile
      -y|+y - assume yes to all questions or not
              Long format: --yes / ++yes 
      -n|+n - assume no to all questions or not
              Long format: --no /++no
      -D|+D - run main in single step mode (and turn colors on); current value: $( ConvertToYesNo "${__DEBUG_MODE}" )
              Long format: --debug / ++debug
      -a|+a - turn colors on/off; current value: $( ConvertToYesNo "${__USE_COLORS}" )
              Long format: --color / ++color
      -O|+O - overwrite existing files or not; current value: $( ConvertToYesNo "${__OVERWRITE_MODE}" )
              Long format: --overwrite / ++overwrite
      -f|+f - force; do it anyway; current value: $( ConvertToYesNo "${__FORCE}" )
              Long format: --force / ++force
       -C   - write a default config file in the current directory and exit
              Long format: --writeconfigfile
      -S n  - print error/warning summaries: 
              n = 0 no summaries, 1 = print error msgs,
              2 = print warning msgs, 3 = print error and warning mgs
              Current value: ${__PRINT_SUMMARIES}
              Long format: --summaries
      -H    - write extended usage to STDERR and exit
              Long format: --doc
      -V    - write version number to STDOUT and exit
              Long format: --version
      -T    - append STDOUT and STDERR to the file "${__TEE_OUTPUT_FILE}"
              Note: This parameter must be the FIRST parameter if used!
              Long format: --tee
${__LONG_USAGE_HELP}

Used environment variables:
$( echo "${__USED_ENVIRONMENT_VARIABLES}" | tr "#" " " )

EOT

  return 0      
}

# -----------------------------------------------------------------------------

## --------------------------------------
## PrintRuntimeVariables
##
## print the values of the runtime variables
##
## usage: PrintRuntimeVariables
##
## returns:  ${__TRUE} - ok
##           ${__FALSE} - error
##           ${__INVALID_USAGE} - invalid usage
##
##
function PrintRuntimeVariables {
  typeset __FUNCTION="PrintRuntimeVariables";    ${__FUNCTION_INIT} ; ${__DEBUG_CODE}

  typeset CURVAR CURVALUE

  typeset __RUNTIME_VARIABLES="
__KSH_VERSION
__SAVE_LANG
__SCRIPTNAME
__REAL_SCRIPTDIR
__CONFIG_FILE
__HOSTNAME
__NODENAME
__OS
__OS_VERSION
__ZONENAME
__OS_RELEASE
__MACHINE_CLASS
__START_DIR
__MACHINE_PLATFORM
__MACHINE_SUBTYPE
__MACHINE_ARC
__LOGFILE
__LOGIN_USERID
__USERID
__RUNLEVEL
"

# init the return code
  THISRC=${__INVALID_USAGE}

# check the parameter count
  CheckParameterCount 0 "$@" || die 240 "Internal error detected"

  if [ $# -eq 0 ] ; then
    THISRC=${_TRUE}

    for CURVAR in ${__RUNTIME_VARIABLES} ; do
      eval CURVALUE="\$${CURVAR}"
      LogMsg "Variable \"${CURVAR}\" is \"${CURVALUE}\" "
    done
  fi

  return ${THISRC}
}


# ??? add user defined subroutines here

## --------------------------------------
## YourRoutine
##
## template for a user defined function 
##
## usage: YourRoutine
##
## returns:  ${__TRUE} - ok
##           ${__FALSE} - error
##           ${__INVALID_USAGE} - invalid usage
##          
##
function YourRoutine {
  typeset __FUNCTION="YourRoutine";   ${__FUNCTION_INIT} ;   ${__DEBUG_CODE}
  
#    typeset __FUNCTION="YourRoutine";     ${__DEBUG_CODE}
   
# init the return code
  THISRC=${__INVALID_USAGE}

# check the parameter count
  CheckParameterCount 0 "$@" || die 240 "Internal error detected"
  
  if [ $# -eq 0 ] ; then
    THISRC=${__FALSE}

# add code here

  fi
  
  echo ""
  echo "LineNo: ${LINENO}; Function ${__FUNCTION} "; trap
  read test

  return ${THISRC}
}

# -----------------------------------------------------------------------------
# main:
#
  
# trace main routine
#
# set -x

# Note: This statement seems to be necessary to use ${LINENO} in the trap statement
#
  LINENO=${LINENO}

# install trap handler
   __settrap

  trap 'GENERAL_SIGNAL_HANDLER exit  ${LINENO} ${__FUNCTION}' exit
  

# trace also all function defined before this line (!)
#
# typeset -ft $( typeset +f )

  InitScript


# ??? init variables with the defaults
#
# format var=${DEFAULT_var}
#

# to process all variables beginning with DEFAULT_ use 
#
  for CURVAR in $( set | grep "^DEFAULT_"  | cut -f1 -d"=" ) ; do
    P1="${CURVAR%%=*}"
    P2="${P1#DEFAULT_*}"

# for debugging
#    push_and_set __VERBOSE_MODE ${__TRUE}
#    push_and_set __VERBOSE_LEVEL ${__RT_VERBOSE_LEVEL}
#    LogInfo 0 "Setting variable $P2= \"$( eval "echo \"\$$P1\"")\" "
#    pop __VERBOSE_MODE
#    pop __VERBOSE_LEVEL
        
    eval "$P2="\"\$$P1\"""
   
  done

    
# --- variables for the cleanup routine:
#
# add mounts that should be automatically be unmounted at script end to this variable
#
#  __LIST_OF_TMP_MOUNTS="${__LIST_OF_TMP_MOUNTS} "

# add directories that should be automatically removed at script end to this variable
#
#  __LIST_OF_TMP_DIRS="${__LIST_OF_TMP_DIRS} "

# add files that should be automatically removed at script end to this variable
#  __LIST_OF_TMP_FILES="${__LIST_OF_TMP_FILES} "

# add functions that should be called automatically at program end to this variable
# before removing temporary files, directories, and mounts
#
#  __EXITROUTINES="${__EXITROUTINES} "    

# add functions that should be called automatically at program end to this variable 
# after removing temporary files, directories, and mounts
#
# __FINISHROUTINES="${__FINISHROUTINES}"

# variables used by getopts:
#    OPTIND = index of the current argument
#    OPTARG = current function character
#
  THIS_PARAMETER="$*"
  
  LogRuntimeInfo "Parameter before getopt processing are: \"${THIS_PARAMETER}\" "

  INVALID_PARAMETER_FOUND=${__FALSE}

  __PRINT_USAGE=${__FALSE}
  CUR_SWITCH=""
  OPTARG=""

# ??? add additional switch characters here
#
  [ "${__OS}"x = "Linux" ] &&  GETOPT_COMPATIBLE="0"

  __GETOPTS=":ynvqhHDfl:aOS:CVT"
  if [ "${__OS}"x = "SunOS"x  ] ; then
    if [ "${__OS_VERSION}"x  = "5.10"x -o  "${__OS_VERSION}"x  = "5.11"x ] ; then
      __GETOPTS=":y(yes)n(no)v(verbose)q(quiet)h(help)H(doc)D(debug)f(force)l:(logfile)a(color)O(overwrite)S:(summaries)C(writeconfigfile)V(version)T(tee)"
    fi
  fi

  while getopts ${__GETOPTS} CUR_SWITCH  ; do

# for debugging only
    if [ 0 = 1 ] ; then 
      echo "CUR_SWITCH is $CUR_SWITCH"
      echo "OPTIND = $OPTIND"
      echo "OPTARG = $OPTARG"
      echo "\$* is \"$*\" "
    fi
    
    if [ "${CUR_SWITCH}" = ":" ] ; then
      CUR_SWITCH=${OPTARG}
      OPTARG=""
    fi

    case ${CUR_SWITCH} in 
    
       "C" ) __WRITE_CONFIG_AND_EXIT=${__TRUE} ;;

      "+D" ) __DEBUG_MODE=${__FALSE}  ;;
      
       "D" ) __DEBUG_MODE=${__TRUE} ; __USE_COLORS=${__TRUE} ;;

      "+v" ) __VERBOSE_MODE=${__FALSE}  ;;

       "v" ) __VERBOSE_MODE=${__TRUE} ; (( __VERBOSE_LEVEL=__VERBOSE_LEVEL+1 )) ;;

      "+q" ) __QUIET_MODE=${__FALSE} ;;

       "q" ) __QUIET_MODE=${__TRUE} ;;

      "+a" ) __USE_COLORS=${__FALSE} ;;

      "a"  ) __USE_COLORS=${__TRUE} ;;

      "+O" ) __OVERWRITE_MODE=${__FALSE} ;;

       "O" ) __OVERWRITE_MODE=${__TRUE} ;;

       "f" ) __FORCE=${__TRUE} ;;

      "+f" ) __FORCE=${__FALSE} ;;
       
       "l" ) NEW_LOGFILE="${OPTARG:=nul}" ;;

      "+l" ) NEW_LOGFILE="nul" ;;

      "+h" ) __VERBOSE_MODE=${__TRUE}
             __PRINT_USAGE=${__TRUE} 
             ;;

       "h" ) __PRINT_USAGE=${__TRUE} ;;

       "T" ) : # parameter already processed but only as first parameter
                [ ${OPTIND} != 1 ] && LogWarning "The parameter -T must be the first parameter if used"
             ;;
       
       "H" ) 

echo " -----------------------------------------------------------------------------------------------------" >&2
echo "                         ${__SCRIPTNAME} ${__SCRIPT_TEMPLATE_VERSION} ">&2
echo "                                Documentation" >&2
echo " -----------------------------------------------------------------------------------------------------" >&2

             grep "^##" "$0" | cut -c3- 1>&2 ; die 0 ;;
                  

       "V" ) LogMsg "Script version: ${__SCRIPT_VERSION}"
             if [ ${__VERBOSE_MODE} = ${__TRUE} ] ; then
               LogMsg "Script template version: ${__SCRIPT_TEMPLATE_VERSION}"
             fi
             die 0 ;;
                

      "+y" ) __USER_RESPONSE_IS="" ;;

       "y" ) __USER_RESPONSE_IS="y" ;;

      "+n" ) __USER_RESPONSE_IS="" ;;

       "n" ) __USER_RESPONSE_IS="n" ;;

       "S" ) case ${OPTARG} in

                0 | 1 | 2 | 3 ) __PRINT_SUMMARIES=${OPTARG}
                                    ;;

                * )  LogError "Unknown value for -S found: \"${OPTARG}\""
                      INVALID_PARAMETER_FOUND=${__TRUE}
                      ;;
                esac
                ;;


# ??? add additional parameter here
     
        \? ) LogError "Unknown parameter found: \"${OPTARG}\" "
             INVALID_PARAMETER_FOUND=${__TRUE}
             break
          ;;

         * ) LogError "Unknown parameter found: \"${CUR_SWITCH}\""
             INVALID_PARAMETER_FOUND=${__TRUE}
             break ;;             

    esac
  done

  case ${__PRINT_SUMMARIES} in 
     0 )  __PRINT_LIST_OF_WARNINGS_MSGS=${__FALSE} 
          __PRINT_LIST_OF_ERROR_MSGS=${__FALSE}
          ;;

    1 )   __PRINT_LIST_OF_WARNINGS_MSGS=${__FALSE} 
          __PRINT_LIST_OF_ERROR_MSGS=${__TRUE}
          ;;

    2 )   __PRINT_LIST_OF_WARNINGS_MSGS=${__TRUE} 
          __PRINT_LIST_OF_ERROR_MSGS=${__FALSE}
          ;;

    3 )   __PRINT_LIST_OF_WARNINGS_MSGS=${__TRUE} 
          __PRINT_LIST_OF_ERROR_MSGS=${__TRUE}
          ;;

    * ) : this should never happen but who knows ...
          __PRINT_LIST_OF_WARNINGS_MSGS=${__FALSE} 
          __PRINT_LIST_OF_ERROR_MSGS=${__FALSE}
  esac
    
  LogRuntimeInfo "Parameter after processing the default parameter are: " "\"$*\" "

  if [ ${__PRINT_USAGE} = ${__TRUE} ] ; then
    if [ ${__VERBOSE_MODE} -eq ${__TRUE} ] ; then
      ShowUsage 
      __VERBOSE_MODE=${__FALSE}
    else
      ShowShortUsage 
      LogMsg "Use \"-v -h\" or \"+h\" for a long help text"
    fi
    die 1 ;   
  fi

  shift $(( OPTIND - 1 ))

  NOT_PROCESSED_PARAMETER="$*"

  LogRuntimeInfo "Not processed parameter: \"${NOT_PROCESSED_PARAMETER}\""
  
   
# ??? add parameter checking code here 
#
# set INVALID_PARAMETER_FOUND to ${__TRUE} if the script
# should abort due to an invalid parameter 
#
  if [ "${NOT_PROCESSED_PARAMETER}"x != ""x ] ; then
    LogError "Unknown parameter: \"${NOT_PROCESSED_PARAMETER}\" "
    INVALID_PARAMETER_FOUND=${__TRUE}
  fi

# exit the program if there are one or more invalid parameter
#
  if [ ${INVALID_PARAMETER_FOUND} -eq ${__TRUE} ] ; then
    LogError "One or more invalid parameters found"
    ShowShortUsage
    die 2
  fi

  SetEnvironment
   
  if [ "${__DEBUG_MODE}" -eq ${__TRUE} ] ; then
     __LIST_OF_TMP_FILES="${__LIST_OF_TMP_FILES} ${__DEBUG_HISTFILE}"

    trap "__LAST_RC=\$?; __LAST_BG_RC=\$!; __LINENO=\${LINENO}; DebugHandler"  DEBUG
:
    echo "INFO: Starting single step mode - works only for the main routine!"
  fi
 
# restore the language setting
#
  LANG=${__SAVE_LANG}
  export LANG

# execute test suite if available
#
  [ -f "./scriptt_test.sh" ] && includeScript "./scriptt_test.sh"

# print some of the runtime variables
#
  PrintRuntimeVariables

# print all internal variables
#
  if [ 1 = 0 ] ; then
    for i in $( set | grep "^__" | cut -f1 -d"=" ) ; do
      echo "$i : \"$( eval echo \"\$$i\" )\" "
    done
  fi

# ??? add your main code here
#  echo "Calling YourRoutine ..."
#   YourRoutine
  
  die ${__MAINRC} 
 
exit

##############################################################################
### This script is submitted to BigAdmin by a user of the BigAdmin community.
### Sun Microsystems, Inc. is not responsible for the
### contents or the code enclosed. 
###
###
### Copyright 2007 Sun Microsystems, Inc. ALL RIGHTS RESERVED
### Use of this software is authorized pursuant to the
### terms of the license found at
### http://www.sun.com/bigadmin/common/berkeley_license.html
##############################################################################


2008/01/02 14:53 2008/01/02 14:53
Posted
Filed under About Knowledge/OS_Unix

어째 다 읽어 보지도 못 하고 글만 올리는것 같습니다.

 나중에 꼭 봐야 지...


1. Shell Program 소개


u      Shell 종류


/usr/bin/sh      POSIX Shell

/usr/bin/ksh     Korn Shell

/usr/old/bin/sh  Bourne Shell

/usr/bin/csh     C Shell

/usr/bin/keysh   Key Shell

/usr/bin/rksh    Restricted Korn Shell

/usr/bin/rsh     Restricted Shell


u      Shell Startup 파일


Korn Shell     /etc/profile -> $HOME/.profile -> $HOME/.kshrc

Bourne Shell   /etc/profile -> $HOME/.profile

POSIX Shell    /etc/profile -> $HOME/.profile -> $HOME/.kshrc

C Shell        $HOME/.login -> $HOME/.cshrc


2.Shell Parameter


u      Parameter Substitution


l         Parameter Setting


# Parameter=Value

# 변수명=값  : Named Parameter


l         Parameter의 Unsetting


# unset parameter

  # unset 변수명

u        Command Substitution


# $(command)       # `command`


# XX="12345"

# echo $XX

12345

# HOST=‘hostname‘

# echo $HOST     : # HOST=`hostname` 문장은 # HOST=$(hostname)과 같다

ssosvr3           : 즉, `command` 문장과 $(command)는 같은 뜻이다

# PS1=‘hostname‘':$PWD# '

# PS1=$(hostname)':$PWD# '; echo $PS1

ssosvr3:/#

# W1="A"; W2="B"; W3="C"

# WORD=${W1}AA${W2}BB${W3}CC

# echo $WORD

AAABBBCCC

# unset WORD

- $10과 ${10}은 다르다. 왜냐하면 $10은 positional parameter $1값에

   0값이 붙여서 출력되며, ${10}은 positional parameter 10번째의 값을

   나타내기 때문이다.


u        Positional Parameter(위치변수)


shell-script  arg1  arg2  arg3  arg4

$0               $1    $2     $3    $4

Positional Parameter : $1,$2,$3,$4

$0          shell script명을 나타낸다

$1          첫번째 argument를 나타낸다. 즉, arg1

$2          두번째 argument를 나타낸다. 즉, arg2

$*          "arg1 arg2 arg3 arg4 ..." 즉,모든 argument와 같다.

$@          "arg1" "arg2" "arg3" "arg4..." 즉,개개의 argument와 같다.

$#          모든 argument의 갯수

$?          마지막으로 수행된 명령어가 return한 값

$$          현재 shell script를 수행하고 있는 shell의 process id(pid)

$!          현재shell에서 수행한 마지막 background의 pid

$_          shell command의 마지막 argument를 가르키며,shell start시에는

            shell의 절대 PATH를 가르킨다.


# set aaa bbb ccc ddd eee fff 

- set명령어를 옵션없이 사용하면 positional parameter를 setting한다.

# echo $0      sh   현재shell를 나타낸다.

# echo $1      aaa

# echo $#      5    $# 은 argument의 개수를 나타낸다.

# echo $*      "aaa bbb ccc ddd eee fff"

# echo $@      "aaa" "bbb" "ccc" "ddd" "eee"

- "$*" 와 "$@" 의 차이점은 $*은 Positional parameter의 모든값을 하나의

  문자열(string)으로 취급하며 $@ 는 string을 개개의 문자열로 취급한다.

# echo $$    7637   : shell의 process id


${parameter}           parameter의 값. 이것은 {}뒤에 붙어있는 문자나

                       숫자,_ 와 같은문자와 함께 사용할 때 필요하다.

${#parameter}          parameter값의 문자수. ${#*}나 ${#@}은 positional

                       parameter의 개수를 나타낸다.

${#identifier[*]}             배열 identifier에서 element의 수를 출력한다.

${parameter:-word}     parameter가 set되고 NOT NULL이면 parameter값을 출력하고,

                       그렇지 않으면 word의 값을 출력한다.

${parameter:+word}     parameter가 set되고 NOT NULL이면 word의 값을 출력하고,

                       그렇지 않으면 아무것도 출력하지 않는다.

${parameter:=word}     parameter가 set되고 NOT NULL이면 parameter의 값을

                       출력하고, 그렇지 않으면 word의 값을 출력하고 parameter에

                       word의 값을 assign한다. Positional parameter는

                       이렇게 setting할 수 없다.

${parameter:?word}     parameter가 set되고 NOT NULL이면 parameter값을

                       출력하고, 그렇지 않으면 word를 출력하고 shell를

                       exit한다. word가 생략되면 화면에 표준출력된다.


# dir1=/home/tmp

# echo ${dir1:-/usr/bin}

/home/tmp

# unset X

# echo ${X:-"X is unset"}

X is unset   : X가 unset또는 null이면 word가 출력된다.

# echo ${dir1:+/usr/bin}

/usr/bin     : dir1이 null이면 아무것도 출력되지 않는다.

# echo ${dir1:=/usr/bin}

/home/tmp    : dir1이 unset되었거나 null이라면 /usr/bin이 출력된다.

# echo ${dir1:?/usr/bin}

/home/tmp

# echo ${#dir1}

10               : /users/tmp 의 총 문자갯수

${parameter#pattern}   pattern이 parameter값의 첫문자와 같으면 그문자를

${parameter##pattern}  포함한 부분은 delete된다. ##은 wild card(*)시 사용함.

   

${parameter%pattern}   pattern이 parameter값을 끝문자와 같으면 그문자를

${parameter%%pattern}  포함한 문자는 delete된다. %%은 wild card(*)시 사용함.


# XX=/a/b/c/d/a/b

# echo ${XX#*a}

/b/c/d/a/b

# echo ${XX##*a}

/b

# echo ${XX%a*}

/a/b/c/d/

# echo ${XX%%a*}

/

# AA="12345123"

# echo ${AA#1}

2345123

# echo ${AA##*1}

23

# echo ${AA%3}

1234512

# echo ${AA%%3*}

12

# echo ${AA#5}

12345123

# echo ${AA##*5}

123

# echo ${AA##*3*}


# echo ${AA##6*}

12345123


u        Tilde(~) Substitution


만약 user mary의 home directory가 /users/mary라면

# echo $HOME

/users/mary

# echo ~           : ~ 는 user의 home directory를 나타낸다.

/users/mary

# echo $PWD

/users/mary/tmp

# ls ~+/x*         : ~ 다음의 + 는 현재directory 즉, $PWD의 값을 가르킨다.

/users/mary/tmp/x_file1

/users/mary/tmp/x_file2

# echo $OLDPWD

/users/mary/mail

# ls ~-/f*         : ~ 뒤의 - 는 이전 directory 즉, $OLDPWD의 값을 가르킨다.

/users/mary/mail/from.mike 

/users/mary/mail/from.nick


u        Shell Command Grouping


l         ( command )  : subshell grouping

                 shell은 마치 또다른 script를 call한것처럼 subshell

                 환경에서 command를 수행한다.

l         { command ;} : brace grouping

                    shell은 현재의 shell 환경에서 연속해서command를

수행하며 마지막에 반드시 ;(세미콜론)을 써야한다.


# vi test1.sh

#! /usr/bin/sh

# (command)의 Example


A="aaa"

B="bbb"

C="ccc"

( A="AAA"

B="BBB"

C="CCC"

echo "PID $$ :

      $A $B $C" )

echo "PID $$ :

       $A $B $C"

:wq

# sh test1.sh

PID 28999 : AAA BBB CCC

PID 28999 : aaa bbb ccc

# vi test2.sh

#! /usr/bin/sh

# {command;}의 Example


A="aaa"

B="bbb"

C="ccc"

{ A="AAA"

B="BBB"

C="CCC"

echo "PID $$ :

      $A $B $C" ;}

echo "PID $$ :

       $A $B $C"

:wq

# sh test2.sh

PID 28955 : AAA BBB CCC

PID 28955 : AAA BBB CCC


u        Shell Script의 수행


# sh shell_script

# ksh shell_script

# chmod 777 shell_script

# ./shell_scipt


u        Shell Script Comment


l         shell script에서 comment는 첫라인에 # symbol를 넣는다.

l         shell script에서 첫라인의 #! /usr/bin/sh의 의미는 이 shell은

    Posix shell로 수행한다는 의미이다.


u        Input and Output


stdin(0)         standard input으로서 default는 keyboard이며

                 file descriptor값은 0 이다.

stdout(1)        standard output으로서 default는 terminal display이다.

                 file descriptor값은 1 이다.

stderr(2)        standard error로서 default는 terminal displsy이다.

                 file descriptor값은 2 이다.

<word            표준입력(file descriptor 0)으로 word를 사용한다.

>word            표준출력(file descriptor 1)으로 word를 사용하며,

word라는 file이 생성된다.

>|word           >word와 같으며 noclobber옵션이 설정되있어도 무조건 overwrite한다.

>>word           word라는 file이 존재하면 file에 append한다.

없으면 word라는file을 생성한다.

<>word           word를 입력으로 받아서 다시 word라는 file로 출력한다.

<<word           shell prompt에서 word라는 글자를 만날때까지 command를 입력할 수

                 있으며 word라는 글자를 만나면 shell command가 수행된다.

<&숫자           file descriptor 숫자의 file에서 data를 입력받는다.

>&숫자           file descriptor숫자를 가진 file로 출력한다.

<&-              표준입력을 close하여 keyboard로부터 입력받지 못한다.

>&-              표준출력을 close하여 terminal로 출력하지 않는다.


# ftp -n -i << AAA

>open mars

>user root password

>cd /users

>mget *

>close

AAA

#


# vi datafile       : data file작성

aaa

bbb

ccc

:wq

# vi read.sh

exec 5< datafile  : datafile을 file descriptor 5번으로 open한다.

read -u5 X        : 첫라인을 read하여 X변수에 assign한다.

read -u5 Y         : 둘째라인을 read하여 Y변수에 할당.

read -u5 Z        : 셋째라인을 read하여 Z변수에 할당.

exec 5<&-         : file descriptor 5번 file을 close한다.

echo "$X $Y $Z"   : file descriptor은 3-9까지 쓸수있다.

:wq

# sh read.sh

aaa bbb ccc






u        조건 표현식


test 또는 [ ... ]             Integer,string.file등에 모두사용(old syntax)

(( ... ))              Integer에만 사용(new syntax)

[[ ... ]]              string,file에만 사용(new syntax)


l         String 표현식  # man test 참조

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

[ -b file ]            file이 존재하고 block special file이면 참

[ -c file ]            file이 존재하고 character special file이면 참

[ -d file ]            file이 존재하고 directory이면 참

[ -e file ]            file이 존재하면 참

[ -f file ]            file이 존재하고 ordinary file이면 참

[ -g file ]            file이 존재하고 setgid bit가 set되있으면 참

[ -h file ]            file이 존재하고 symbolic link되었으면 참

[ -k file ]            file이 존재하고 sticky bit가 set되었으면 참

[ -p file ]            file이 존재하고 fifo special file또는 pipe이면 참

[ -r file ]            file이 존재하고 readable하면 참

[ -s file ]            file이 존재하고 file size가 0보다 크면 참

[ -u file ]            file이 존재하고 setuid bit가 set되 있으면 참

[ -w file ]            file이 존재하고 writable하면 참

[ -x file ]            file이 존재하고 executable하면 참

[ -L file ]            file이 존재하고 symbolic link이면 참

[ -O file ]            file이 존재하고 user가 effective user id와 같으면 참

[ -G file ]            file이 존재하고 group이 effective group id와 같으면 참

[ -S file ]            file이 존재하고 socket이면 참

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

[ -n string ]          string의 길이가 non zero면 참

[ -z string ]          string의 길이가 zero이면 참

[ string ]                    string이 not null string이면참





# if [ -f /etc/rc.config ] ; then

# if [ ! -d /usr/bin ] ; then

# if [ -z "$NODENAME" ] ; then

# if [ -x /usr/dt/bin/dtrc ] ; then

# if [[ -n "$NAME" ]] ; then

# if [[ -s /var/spool/lp/pstatus ]] ; then

# if [[ -r /var/run/mrouted.pid ]] ; then

# if [[ -z "$pid" ]] ; then

# if /usr/sbin/envd ; then

# if /sbin/local_is_root ; then

# if [ "$ARRAYMON_PID" ] ; then

# if [ "$START_OV500" ] ; then


[ file1 -nt file2 ]    file1이 존재하고 file2보다 newer이면 참

[ file1 -ot file2 ]    file1이 존재하고 file2보다 older이면 참

[ file1 -ef file2 ]    file1이 존재하고 file2와 equal file이면 참


# if [ /sbin/init.d/spa –nt /sbin/init.d/set_date ] ; then

# if [ /aaa –ot /bbb ] ; then

# if [ /ccc –ef /ddd ] ; then


[ string1 = string2 ]  string1과 string2가 같으면 true

[ string1 = pattern ]  string1과 pattern이 같으면 true

[ string1 != string2 ] string1과 string2가 같지않으면 true

[ string1 != pattern ] string1과 pattern이 같지않으면 true

[ string1 < string2 ]  string1이 string2보다 작으면 true

[ string1 > string2 ]  string1이 string2보다 크면 true


# if [ "$pid" = "" ] ; then

# if [ X$pid != "X" ] ; then

# if [ $HOST != `hostname` ] ; then

# if [ "$MWASTART" > "1" ] ; then

# if [[ $? = 255 ]] ; then


[ exp1 -eq exp2 ]             exp1과 exp2가 같으면 참(equal)

[ exp1 -ne exp2 ]             exp1과 exp2가 같지 않으면 참(not equal)

[ exp1 -lt exp2 ]             exp1이 exp2보다 작으면 참(less than)

[ exp1 -gt exp2 ]             exp1이 exp2보다 크면 참(greater than)

[ exp1 -le exp2 ]             exp1이 exp2보다 작거나 같으면 참(less than or equal)

[ exp1 -ge exp2 ]             exp1이 exp2보다 크거나 같으면 참(greater than or equal)


# if [ $x –ne 0 ] ; then

# if [ $? –eq 0 ] ; then

# if [ "$RWHOD" –eq 1 ] ; then

# if [[ "$rval" –eq ${EXIT_NA} ]] ; then

# while [ ${CNT} –le ${MAX_NISCHECKS} ] ; then

# if [ $# -ge 0 ] ; then

# if [ "$XX" –gt "$YY" ] ; then

# if [ "$X" –lt 1 ] ; then

# if [ $# -ne 1 ] ; then

# if [ `grep $HOSNAME /etc/mail/sendmail.cw|wc –l` -eq 0 ] ; then


( expression )         expression이 참이면 참

! expression           Binary NOT 연산자

exp –a exp2            Binary AND 연산자, 우선순위가 –o 보다 높음.

exp –o exp2            Binary OR 연산자

exp1 && exp2           exp1과 exp2가 모두 참이면 참

exp1 || exp2           exp1가 참이거나 exp2가 참이면 참


# if [ "$GATED" –eq 0 –a "X$pid" = "X" ] ; then

# if [ "$CRON" –eq 1 –a –x /usr/sbin/cron ] ; then

# if [ "$NIS_DOMAIN" –a –f /usr/bin/domainname ] ; then

# if [ "$NIS_MASTER" –ne 0 –o "$NIS_SLAVE" –ne 0 ] ; then

# if [ "$9" = 'S' ] || [ "$9" –lt '2' ] ; then

# if [ "$VTDAEMON_START" –eq 1 ] && [ -x /usr/sbin/vtdaemon ] ; then

# if [[ -r /usr/sbin/swagentd# ]] && [[ -h /usr/sbin/swagentd ]] ; then

# if [ $status !=2 –o –z "$DOMAIN" –o –z "$SERVER" ] ; then

# if (( status == 0 )) && [[ -n $PROTO ]] ; then


l         Integer 표현식


(( integer1 == integer2 ))    integer1과 integer2가 같으면 참

(( integer1 != integer2 ))    integer1과 integer2가 같지 않으면 참

(( integer1 < integer2 ))           integer1이 integer2보다 작으면 참

(( integer1 > integer2 ))           integer1이 integer2보다 크면 참

(( integer1 <= integer2 ))    integer1이 integer2보다 작거나 같으면 참

(( integer1 >= integer2 ))    integer1이 integer2보다 크거나 같으면 참


# if (( $? != 0 )) ; then

# while ((n>0))

# if ((n<2) || !length(part[2])) ; then

# if ( $1 != mypid ) ; then

# if (( $1 > $2 )) ; then


3.Shell Programming


u        if 조건문


if 조건문

then

   명령어

[elif 조건문

then

   명령어]

[else

   명령어]

fi


if 조건문; then 명령어; [elif 조건문; then 명령어;] [else 명령어;] fi


:wq# vi if1.sh

X=hello

if [ $X = hello ]

then

   echo "Welcome"

else

   echo "Goodbye"

fi

:wq

# sh if1.sh

Welcome

# vi if2.sh

if [ -f temp ]

then

   mv temp temp1

elif [ -f temp1 ]

then

   mv temp1 temp2

fi

:wq

# sh if2.sh


u        case 조건문


case 변수 in

변수값1|변수값2…)

   명령어;;

변수값3|변수값4…)

   명령어;;

*)

   명령어;;

esac





#  vi case.sh

case $1 in

-d|-r)

        rmdir $dir1

        echo "directory removed" ;;

-o)

        echo "option -o" ;;

*)     

        echo "Invalid option,Try again..." ;;

esac

:wq

# chmod 777 case1.sh

# ./case.sh -o

option -o


u        while 반복문


while 조건문

do

   명령어

done


- 다음은 모두 같은 while문이다.


while [ 1 ]

do

  echo "Test"

done

while true

do

  echo "Test"

done

while [ : ]

do

  echo "Test"

done

while :

do

  echo "Test"

done


# vi while1.sh

count=$(who|grep -v root|wc -l)

while [ "$count" -gt 0 ]

do

   echo "Users still logged in..."

   sleep 1

   count=$(who|grep -v root|wc -l)

done

:wq

# sh while1.sh


# vi while2.sh

# /usr/bin/sh

#

print -n "Enter a value : "

read Value

print "Thank You"

count=0

while [ "$count" -lt "$Value" ]

do

   (( count=count + 1 ))

   print "Still sleeping for the $count th time..."

   sleep 2

done

print "End of $0"

:wq

# sh while2.sh


u        for 반복문


for 변수 [in 변수값1,변수값2,…]

do

   명령어

done


# vi for1.sh

for name in $(cut -d -f1 /etc/passwd)

do

   mailx $name < message.txt

   echo "Mail sent to $name"

done

:wq

# sh for1.sh

# vi for2.sh

if [[ ! -d "$1" ]]

then

   exit 1

fi

filename=$(ls $1)

for onefile in $filename

do

   if [[ -f ${1}/$onefile ]]

   then

      ll ${1}/$onefile

   elif [[ -d ${1}/$onefile ]]

   then

      ll -d ${1}/$onefile

   fi

done

:wq

# sh for2.sh /etc







u        until 반복문


until 조건문

do

   명령어

done


# vi until.sh

count=$(who|grep -v root|wc -l)

until [ "$count" -eq 0 ]

do

   echo "Users still logged in..."

   sleep 1

   count=$(who|grep -v root|wc -l)

done

:wq

# sh until.sh


u        select 반복문


select 변수 [in 변수값1,변수값2,…]

do

   명령어

done


- select문은 PS3 prompt를 사용한다. PS3 shell 변수의 기본값은 #? 이다.

- 변수는 변수값1,변수값2,… 등이 할당된다.

- 입력된 변수의 값의 숫자는 REPLY라는 shell변수에 저장된다.

- exit,return,break 등의 명령어로 반복문을 빠져나올수 있다.

- [in 변수값1,변수값2,…]가 없을경우에는 Positional Parameter를 사용한다.


# vi edit.sh         ### Edit the file ###

select menu in $(ls) "Exit" ; do

   case $menu in

     Exit) exit;;

     "") echo "Invalid selection. Try again!";;

     *) cp $menu $menu.bak; vi $menu ;;

   esac ; done

:wq





# vi color.sh

  select color in red blue green

  do

     echo "$color is an $color color"

     echo "$REPLY is a REPLY value"

  done

:wq

# sh color.sh

1)red

2)blue

3)green

#? 1

red is an red color

1 is a PEPLY value

#? 2

blue is an blue color

2 is a REPLY value

#? ^C

#


# vi select.sh

PS3="Enter your choice =>"

select menu in "full backup"

                  "partial backup"

do

 case $menu in

 "full backup")

  fbackup –0uf /dev/rmt/0m –i /stand

  echo "Full backup has begun"

  exit 0;;

 "Partial backup")

fbackup –0uf /dev/rmt/0m -i /opt

echo "Partial Backup has begun"

return;;

 *) echo "$REPLY is an invalid

             option. Try again!";;

 esac

done

:wq

# sh select.sh


# vi nest.sh

  #### Nested Select Command Example ###

#! /usr/bin/sh

PS3="Main Choice by number=>"

select menu in "List Files" "Exit"

do

   case $menu in

   "List Files")

      PS3="Sub Choice by number=>"

      select ls_option in "Short" "Long" "Main"

      do

         case $ls_option in

          "Short") lsf;;

           "Long") ll;;

           "Main")

               PS3="Main Choice by number=>"  ## Restore Prompt

               break 1 ;;  ## exit inner loop

           "") echo "$REPLY is an invalid option. Try again!";;

         esac

      done ;;

   "Exit") exit;;

   "") echo "$REPLY is an invalid option. Try again!";;

   esac

done

:wq

# sh nest.sh





u        Function(함수)


function 함수명

{

  shell script

}

함수명()

{

  shell script

}


- shell script안에 선언할수도 있고 밖에 선언할수도 있다.

- 함수명이나 argument로 called될수 있다.

- 같은 process를 반복적으로 사용할때 유리하며 debugging하기가 쉽다.

- typeset -xf name 으로 함수명을 export하여 global 함수로 선언할수 있다.


# vi func1.sh

function exef

{

   if [ -x $1 ]

   then

      echo "$1 is executable"

   fi

}

for file in `ls`

do

   exef $file

done

:wq

# sh func1.sh


# vi func2.sh

Uppercase()

{

   echo $* | tr "[a-z]""[A-Z"]"

}


print -n "Enter in a string:"

read string

upper_string=$(Uppercase $string)

echo "The uppercase string is: $upper_string"

:wq

# sh func2.sh







# vi func3.sh       : Recursive Fuction

bottom_up

{

   typeset SAVEPWD

   echo "\nDirectory being listed is: $PWD\n"

   lsf

   if [ "$PWD" != "/" ]

   then

      SAVEPWD=$PWD

      cd ..

      bottom_up

      cd $SAVEPWD

   else

      echo "That's the end!"

   fi

}

:wq

# sh func3.sh


u        Array(배열)


- shell script에서 사용할수 있는 배열은 1차원배열이다.

- 배열요소(element)는 최대 512-1024까지 쓸수 있다.

- 배열요소는 [0]부터 [1023]까지 쓸수 있다.

- Array subscript인 [N]에서 N은 integer또는 integer expression을 쓸수 있다.


# X[0]=first

# X[1]=second

# X[2]=third

# echo ${X[1]}

second

# echo ${X}         : ${X}는 ${X[0]}과 같음

first

# echo ${X[*]}             : '*'나 '@'는 모든 요소를 가르킴

first second third

# echo ${#X[*]}

3

# i=3

# X[2*(i+1)]=10

# print ${X[8]

10



# set -A YY 100 200 300    : set -A는 변수를 배열로 선언한다.

# print ${YY[0]} ${YY[1]} ${YY[2]}

100 200 300

# set +A YY 150

# print ${YY[@]}

150 200 300




4.Shell Command


u        : 명령어


- ':' 명령어는 아무것도 수행하지 않으며, 어떤 영향도 미치지 않는다. '0'값이 return됨.


# vi xx.sh

if [ -f /opt ]; then

   ls

else

   :            아무것도 수행하지 않는다.

fi

:wq


u        . 명령어


# . /etc/profile


- /etc/profile이라는 프로그램을 수행한다. 이는 sh나 ksh처럼 또하나의 shell을 fork하여

  프로그램을 수행하지 않으며 이 프로그램은 수행가능한 permission이 없어도 된다.

  즉 이 파일은 'x' permission이 없어도 된다.


u        alias 명령어


alias [-x] [ name[=value] … ]


# alias                             : 현재 setting된 모든 alias를 display

# alias a=alias

# a x=lsf

# alias i='

> echo Users logged in are:

> who|sort

> echo I am `whoami`'

# i                                  : alias문을 수행한다.

# unalias i                        : alias변수 i를 unsetting한다.

# unalias -a                       : shell command에서 typing한 모든

                                        alias를 해제한다.

# alias -x who='who|sort'       : Korn shell에서 who를 export하여

                                        subshell에서도 사용가능하다.


u        break 명령어


break [n]


- for,while,until,select문과 같은 반복문에서 exit할 때 사용한다.

- n을 쓰면 n레벨만큼 loop를 exit한다.


# vi break.sh

for file in x y z none

do

   if [ -x $file ]; then

      echo $file

      break

   fi

done

:wq


u        command 명령어


command [arg …]


- argument를 command로서 취급한다.


# command lsf       : lsf를 command로 사용한다.

# command aaa       : aaa를 command로 사용한다.


u        continue 명령어


continue [n]


- for,while,until,select문과 같은 반복문에서 continue이하의 문을 수행하지 않고

다시 시작한다.

    - n을 쓰면 n번째 반복문을 다시 시작한다.


# vi con.sh

for file in x y z

do

   if [ -x $file ]; then

      continue

      echo "$file is executable"

   fi

   echo $file is not executable

done

:wq


u        echo 명령어


echo [arg …]


# echo 'This is a' $var 'example.'

# echo "This is a $var example."

# echo "Enter your user name: \c"

> read user

> echo 'User is' $user


echo 에서 Escape Character

\b     backspace

\c     continue line. new line을

       하지 않고 계속 붙여서 print한다

\f     form feed

\n     new line

\r     carriage return

\t     tab

\v     vertival tab

\\     backslash


u        eval 명령어


eval [arg …]


- argument를 input으로 받아서 명령어로 수행하며 argument는 command나 shell

  script가 될수 있다.


# cmd='ps -ef > ps.out'

# eval $cmd

# eval "grep jones $file|set|echo $1 $2 $3"


u        exec 명령어


exec [arg …]


- 새로운 process나 subshell을 만들어서 argument를 수행하지 않고 현재 shell로

  명령어를 바로 수행한다.

# exec 3< file          file desciptor number 3으로 file을 open한다.

# ecec 2> /dev/null     표준에러를 /dev/null로 출력한다.


u        expr 명령어         # man expr 참조


expr expression {+,-,\*,/} expression

expr expression {=,\>,\>=,\<,\<=,!=} expression

expr string1 : string2


# a=15

# expr $a + 5

20

# count=`expr $count + 5`

# A=batman

# expr substr $A 1 3

bat

# expr index $A m

4


u        fc 명령어


fc [-r] [-e example] [first [last]]

fc –l [-nr] [first [last]]

fc –s [old=new] [first]

fc –e – [old=new] [command]


- fc command는 history file을 list하거나 history file에서 command를 edit할 수있다.


# fc –l            : history file의 내용을 display한다.

# fc –l 20 25

# fc –l 10

# fc –e vi 15 20

# fc –e -          : 방금 실행한 command를 다시 실행한다. # r 명령과 같다.

# fc –e – ls=cd  


u        let 명령어


let "expression"

(( expression ))

- let는 산술 표현을 가능하게 하며 long integer 계산을 한다.


Operator

Description

-

!

/  %

+  -

<  <=  >  >=

==  !=

=

unary minus

logical negation

곱하기,나누기,몫

더하기,빼기

비교

같다,같지 않다

변수 할당


# x=10

# y=2

# let x=x+2

# echo $x

12

# let "x=x/(y+1)"

# echo $x

4

# (( x=x+1 ))

# echo $x

5

# x=12

# let "x<10"

# echo $?

1

# (( x > 10 ))

# echo $?

0

# if (( x > 10 ))

>then echo x greater

>else echo x not greater

>fi

x greater


u        read 명령어


read [-r] name…        : POSIX Shell only

read [-prsu] [name]    : Korn Shell only


-r          라인연속으로 쓰인 라인끝의 \를 해석하지 않는다.

-un         file descriptor n 으로부터 input을 read한다.


# vi read.sh

  while read -r xx yy

  do

     printf "%s %s \n" "$yy" "$xx"

done < input_file

:wq


u        return 명령어


return [n]


- 함수의 실행을 마치고 calling shell script에게 exit status n을 return한다.

- n이 없으면 return status는 함수의 마지막 command의 값이다.

- return이 함수의 밖에서 수행되면 exit로서 실행된다.


# vi return.sh

  search()

  {

     if grep xxx "$1" > /dev/null 2>&1

     then return 1

     else return 2

     fi

  }

:wq

# sh return.sh filename


u      set 명령어


l         Positional Parameter값 setting


# set spring summer fall winter

# echo $3

fall

# echo $*

spring summer fall winter



l         Positional Parameter Sorting


# set third first second

# echo $1 $2 $3

third first second

# set –s               : 값을 lexical order로 sorting함

# echo $1 $2 $3

first second third

# set +s            : unsetting








option         option-name meaning

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

set –a         allexport   모든 parameter가 자동으로 export됨. == set -o allexport

set -C         noclobber   #date>XX시 >로 overwrite하지못하게 함. date>|XX로는 가능

set –e         errexit     shell command fail시 즉시 logout또는 shell을 exit함

set –f         noglob             # ls * 시wild card문자를 인식못함

set –h         trackall   

set –k         keyword    

set –m         monitor     Background jogs이 각각다른 process group에서 수행되고

                           작업이 끝나면 message를 report함

set –o                     set –o monitor와 같이 option-name에 붙여서 옵션을

                           setting함

set –s                     positional parameter를 sort함

set –t                     shell을 exit한후에 command를 수행함

set –u         nounset     substituting시 unset parameter를 error로 취급함

set –v         verbose     command를 display한후 command 수행

set –x         xtrace             command수행시 command와 argument까지 print함.

                           shell script의 debug mode로 사용함.

              

set                        현재 setting된 모든 shell variable을 list함

set -                      -x와 –v option을 turn off하고 flag에 대한 argument

                           검사를 하지 않음

set --                     옵션의 어떤 변화도 하지못하게 함. # set -- -;echo $1

                                      file명으로 시작하는 file을 rm할 경우 # set -- -;rm –aaa


# set –o ignoreeof          : ignoreeof라는 옵션을 turn on

# set +o vi                : vi의 옵션을 turn off

# set –o noglob            : noglob옵션을 turn on 시키고 wild card인

                                    *,[],-,!,? 등을 shell이 해석하지 못하게함

# set –o noexec            : shell의 syntax error를 check하기위해 사용.

                             이 옵션은 interactive shell에서는 사용되지

                                    않으며 shell script에서만 수행됨.

                             noexec 옵션은 실제로 shell을 수행하지 않으면서

                                       shell의 syntax error만을 check하는 명령어다.



# vi set1.sh

  set –o noexec

  echo "This is test

  ls

  cp /aaa /bbb

:wq

# ksh set1.sh

set1.sh: syntax error at line 2 : '"' unmatched

# vi set2.sh

  set –x

  ls

  echo "The Test"

  set +x

  lsf

:wq

# sh set2.sh


u        shift 명령어


shift [n]


shift command는 positional parameter($1,$2,$3..)의 내용을 왼쪽순으로 move한다.


# vi shift1.sh

  yflag=0

  zopt=""

  for arg in "$@"

  do

     if [ "x$arg" = x-y ]

     then

        yflag=1

        shift

     else

       zopt="$2"

       shift 2

     fi

  done

:wq


u        trap 명령어


trap [command] [signal]


- signal 값은 # kill –l또는 # man kill 명령어로 볼수 있음.

# trap "echo 'Command Failed'" 2

                       : ^C(interupt)를 치면 echo 문장이 수행됨.


# trap              : trap 명령을 수행한후 옵션이 없이 trap명령을 수행하면 현재

                    setting된 모든 trap내용을 보여줌

# trap "" 1 2 3

                       : 1}HUP 2)INT 3)QUIT가 입력되도 무시하라.

# trap "echo logout" 0

                       : signal이 '0' 이면 NULL signal로서

                         shell에서 exit할때 command가 수행된다.


u      typeset 명령어


typeset [-][+]옵션  변수명[=변수값]


option      meaning

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

[-]         변수명의 속성을 setting

[+]         변수명의 속성을 turn off

-Ln         왼쪽의 공백을 제거하고 왼쪽에서 n숫자만큼 cut

-Rn         왼쪽에 공백을 채우고 오른쪽에서 n숫자만큼 cut

-Z          오른쪽으로 shift하고, 첫번째 문자가 숫자이고 –L옵션과 같이

            쓰지 않았으면 왼쪽에 숫자0을 채움

-i          변수명을 integer로 선언

-f          변수명이 아니라 함수명으로 변수를 선언

-l          모든 영문대문자를 소문자로 변환

-u          모든 소문자를 대문자로 변환

-r          변수를 read-only로 만듬,즉 변수를 상수로 만듬

-x          변수를 export함, 즉 변수를 전역변수로 만듬

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

# typeset

현재 setting되어있는 변수의 data type을 보여줌

# typeset AA

AA변수를 string변수로 선언,또한 함수내에서 Local변수 즉 지역변수로 선언

하지만, shell에서 변수는 default로 string data type임


# DATA="Today we had very HOT weather"

# typeset –u DATA

# echo $DATA

TODAY WE HAD VERY HOT WEATHER

# typeset +u DATA : DATA변수의 속성을 turn off 

# DATA="as of the "${DATA}

# echo $DATA

as of the TODAY WE HAD VERY HOT WEATHER


# AAA=123456789

# typeset –L3 AAA

# echo $AAA

123


# typeset –LZ X=00005

# print $X

5

# typeset –i X        : 변수X를  integer로 선언 # integer X와 같음

# typeset –i2 X     : 변수X를 2진수로 선언

# typeset –i8 X     : 변수X를 8진수로 선언

# typeset –i10 X    : 변수X를 10진수로 선언

# typeset –i16 X    : 변수X를 16진수로 선언

# typeset -r Y=123  : 변수Y를 readonly변수로 선언 # readonly Y=123과 같음

# typeset -f        : 모든함수와 그 값을 display함

# typeset -xf       : export된 모든함수와 그 값을 display함

# typeset -xf XX    : 함수명 XX를 export하여 global function으로 선언함


u        ulimit 명령어


ulimit  [-f] [n]


- ulimit command는 child process나 subprocess에 의해 사용된는 resources를 제한한다.


# ulimit               : 현재 limit값을 보여준다

# ulimit –f 1000       : 현재process나 향후 process가 write할 수 있는

                          file size를 1000 block(1000*512 byte)으로 제한한다.

# ulimit –f unlimited : child process가 생성할 수 있는 size의 제한을 없앤다.







5.Regular Expression(정규 수식)


u        Pattern Matching과 Regular Expression의 비교 - # man 5 regexp참조


Pattern Matching


Regular Expression

- POSIX shell에서 사용

- file name생성과 case문에서 사용

- UNIX command와 Text Editor에서 사용

  (ed,vi,ex,sed,awk,expr,grep)

- file name을 match한다

- character string을 match한다

- file name을 substitute한다

- string을 search해서 substitute한다

- 사용되는 특수문자

  ?,  *,  [ - ],  !

- 사용되는 특수문자

  .,  [],  -,  ^,  $,  *


u        하나의 문자와 Match - .(dot)


A.          : AB,Ab,AA,A9등과 같이 A다음에오는 어느한문자와 match

...         : 연속된 3문자와 match

# man 5 regexp|col -b|expand > regexp.man

# grep 'RE.' regexp.man       : RE다음에오는 어느한문자와 Match되는 라인만 출력


u        문자의 시작과 Match - ^


^abc        : 첫문자가 abc로 시작되는 문자와 match. abc,abcabc,abcdef등과 match

^C          : 문자의 시작에서 C와 match

^C$         : 하나의 문자 C와 match

^.$         : 하나의 문자로만 구성된 문자와 match

^[ABC]      : 첫문자가 ABC로 시작되는 문자와 match


u        문자의 끝과 Match - $


abc$        : 끝문자가 abc로 끝나는 문자와 match. defgabc,cccabc,abc등과 match

^...$       : 3개의 문자로만 구성된 문자와 match

\.$         : 문자의 끝에서 마침표(.)과 match

\*$         : 문자의 끝에서 (*)와 match



u        문자 Match - []


[Tt]he      : The나 the라는 글자를 search

h[iau]t     : hit,hat,hut의 글자와 match

[ABC]       : A,B,C를 포함하는 문자와 match


u        범위를 포함하는 문자와 Match - [ - ]


[a-z]       : 소문자 a부터 z까지 어느문자와도 match

[0-9]        : 0-9까지 어떤 하나의 숫자와 match

[0-57]      : 0,1,2,3,4,5,7과 match

[a-c5-8X-Z] : a,b,c,5,6,7,8,X,Y,Z중 하나의 문자와 match

[0-3-]      : 0,1,2,3,-와 match


u        Complemented문자 Match - [^  ]


[^ ]        : 공백이 아닌 한문자와 match

[^0-9]      : 0-9까지 숫자가 아닌 하나의 모든문자와 match

[^a-zA-Z]   : 영문 알파벳이 아닌 문자나 숫자와 match

[012^]      : 0,1,2,^와 match

^[^a-z]$    : 소문자을 제외한 나머지 문자중 하나와 match

# man 5 regexp|col -b|expand > regexp.man

# grep '^$' regexp.man|wc -l         : 공백라인수를 출력한다.

# TMOUNT=`/sbin/mount | grep '^/tmp(/| )' | wc -l`

# grep -q -e "^/usr/bin$" -e "^/usr/bin:" -e ":/usr/bin:"\

         -e ":/usr/bin$" /etc/PATH


u        Null 또는 여러 같은문자와 Match - *,+,?


B*          : Null문자,B,BB,BBB...등과 match

AB*C        : AC,ABC,ABBC...등과 match

A+          : A,AA,AAA...등과 match

AB+C        : ABC,ABBC,ABBBC...등과 match

A?          : Null문자 또는 A와 match

AB?C        : AC,ABC와 match

[A-Z]+      : 하나이상의 대문자와 match

(AB)        : AB문자와 match

(AB)+C      : ABC,ABABC,ABABABC...등과 match

AB.*XYZ     : ABXYZ,ABCXYZ,ABCCCCXYZ...등과 match


u        특수문자 Match - \


\*          : 특수문자 *와 match

\$          : 특수문자 $와 match

\\          : 특수문자 \와 match

\\\\\.\*$   : 문자의 끝에서 \\.* 와 match


u        Subexpression - \( ... \)


- \(...\)구문을 사용한다.

- subexpression과 match하는 문자를 recall하기위해 '\숫자'를 사용한다.

- '\숫자' 는 1-9까지 쓸수있다.

- \1 은 1번째 subexpression,\2 는 2번째 subexpression을 나타낸다.


# who

root       console      Oct 23 13:01

root       ttyp1        Oct 27 12:45

root       pts/0        Oct 22 09:03

# who|sed 's/\([^ ][^ ]*\)[^A-Z][^A-Z]*\(.*\)/\2-->\1/'

Oct 23 13:01-->root

Oct 27 12:45-->root

Oct 22 09:03-->root

- 첫번째 /\([^ ][^ ]*\) 는 공백이 아닌 하나이상의 문자와 match하며 뒷부분의

  \1 의 값과 같다.즉, 여기서는 username root를 가르킨다.

- 두번째 \(.*\) 는 최초로 대문자로 시작되는 문자와 match하며 뒷부분의

  \2 의 값과 같다. 여기서는 Oct를 가르킨다.



6.Sed(Stream Editor)


u        sed 형식


sed [-n] command input_file...

sed [-n] [-e command]... [-f script_file]... [input_file...]


-n          화면에 display하지 않는다. 단  p명령어일경우는 화면에 display한다.

            -n옵션은 -e나 -f옵션중 하나와 같이 사용할수 있다.

-e command  command를 editing하며, input file이 없으면 표준입력이 사용된다.

-f script   input file에서 editing command의 script file을 수행한다.


- sed는 입력파일로부터 한라인씩 data를 read한다.

- sed는 default로 화면에 출력을 하며 input file을 modify하지 않는다.


# sed "s/UNIX/Unix/g" file1 > file2.new

# sed -e "s/Miss/Ms/g" -e "s/Mrs/Ms/g" file2

# sed -n "1,10p" file2

# cat script

1,10p

# sed -n -f script file2


u        s(substitute)


[address [,address]] s/string_old/string_new/[flag]


flag        meaning

g           global substitution(전라인을 모두바꾼다)

p           print line

w file      file로 write한다


# sed "s/[Cc]omputer/COMPUTER/g" file1

# sed -e "1,5s/abc/xyz/" -e 's/kbs/mbc/' file1 > file2

# sed "/abcde/s/ab/AB/g" file1

# sed -e 's/abc/xyz/w file2' file1

# sed "3s/the/xyz/g" file1

# sed '3s/^the /xyz/' file1

# sed -e "/the/s/ for /xyz/g

# cat file1| sed "/the/s/ for /xyz/gw file2

# sed "1,8s/aaa/bbb/g" file1 > file2

# sed "/^5/,/^15/s/from/FROM/g"

# sed -e "/^The first time/,/^End of file/s/lsf/ll/g"

# sed "1,$s/\/usr\/bin/\/sbin\/bin/g"


u        d(delete)


# sed "1,10d" fileA

   - fileA에서 1-10라인까지 delete한다.

# sed "/^From/!d" mbox

   - mbox file에서 From으로 시작되는 라인만 제외하고 모두 delete한다.


u        p(print),l(list),=,q(quit),r(read),w(write)


p           standard output에 print한다. -n옵션과 함께써도 print된다.

l           nonprinting문자도 같이 표준출력한다.

=           address 라인의 라인번호를 표준출력한다.

q           현재라인을 출력하고 sed를 종료한다.

r file      file의 내용을 read하여 표준출력한다.

w file      file에 address라인을 write또는 append한다.


# vi cap

   One potato, teo potato,

   three potato, four.

   Five potato, six potato,

   seven potato, more.

:wq


# sed -n "1,2p" cap

One potato, two potato,

three potato, four.


# sed -e "q" cap

One potato, teo potato,

# sed -e "/\./=" -e " /[A-Z]/w file1" cap

One potato, teo potato,

2

three potato, four.

Five potato, six potato,

4

seven potato, more.


# killproc() {

      for x in "$@"

      do

         pid=`ps -e |grep "$x" |sed -e 's/^  *//' -e 's/ .*//'`

         [ ! –z "$pid" ] && echo killing $x && kill $pid &

      done

  }

# findproc() {

    pid=`ps –e |grep "$1" |sed -e 's/^  *//' -e 's/ .*//'`

    echo $pid

  }

# killproc() {           

      echo stopping $1

      pid=`/usr/bin/ps -e |

            /usr/bin/grep "$1" |

            /usr/bin/sed -e 's/^  *//' -e 's/ .*//'`

            [ "$pid" != "" ] && kill $pid

  }

# if [ "$RWHOD" –ne 1 ]; then

      rval=2

  else

      pid=`ps -el | awk '( ($NF ~ /rwhod/) && ($4 != mypid) &&

           ($5 != mypid)) { print $4 }' mypid=$$ `

      if [ "X$pid" != "X" ]; then

         if kill $pid; then

            echo "rwhod stopped"

         else

            rval=1

            echo "Unable to stop rwhod"

         fi

      fi

  fi

#

#

#

# ARRAYMON_PID=`ps -ef | awk '$0 ~ /.*arraymon*/ && $0 !~ /.*awk.*/

                  { print $2 }'`

  if [ "$ARRAYMON_PID" ]

  then

     echo "Killing disk array monitor daemon."

     kill -9 $ARRAYMON_PID

     sleep 2

     ARRAYMON_PID=`ps -ef | awk '$0 ~ /.*arraymon*/ && $0 !~ /.*awk.*/

                     { print $2 }'`

     if [ "$ARRAYMON_PID" ]

     then

       echo "ERROR:  Could not kill ${ARRAY_MONITOR_DAEMON}"

     fi

  fi

#




























7.Shell Program 예제


-shell script를 위한 data file은 다음과 같다.

# vi data

  100 200 300 400

  500 600 700 800

  900 1000 1100 1200

  1300 1400 1500 1600

  1200 800 400 0

:wq

# vi exp1.sh

if [[ ! -f "$1" ]]

then

   echo "${0##*/}"

   exit 1

else

   filename=$1

fi

exec 3< $filename : file descriptor 3으로 filename를 open

typeset -i II=0   : XX를 integer로 선언

while read -u3 AA[0] AA[[1] AA[2] AA[3]

do

   for II in 0 1 2 3

   do

      (( total[II]=${total[II]} + ${AA[II]} ))

   done

print "Subtotal : "

print ${total[*]}

done

print "Total for the four columns are : "

print ${total[@]}

:wq

# sh exp1.sh












#!/usr/bin/sh

######################## /etc/profile ##########################  


trap "" 1 2 3                   

PATH=/usr/bin:/usr/ccs/bin:/usr/contrib/bin

MANPATH=/usr/share/man:/usr/contrib/man:/usr/local/man

if [ ! -d /usr/sbin ]

then

   PATH=$PATH:/sbin

else

   if [ -r /etc/PATH ]

   then

      grep -q -e "^/usr/bin$" -e "^/usr/bin:" -e ":/usr/bin:"\

                -e ":/usr/bin$" /etc/PATH

      if [ $? -eq 0 ]

      then

         PATH=`cat /etc/PATH`

      else

         PATH=$PATH:`cat /etc/PATH`

      fi

   fi

fi

export PATH

if [ -r /etc/MANPATH ]

then

   MANPATH=`cat /etc/MANPATH`

fi

export MANPATH

if [ -r /etc/TIMEZONE ]

then

   . /etc/TIMEZONE 

else

   TZ=MST7MDT       

   export TZ

fi

if [ ! "$VUE" ]; then

   if [ "$TERM" = "" -o "$TERM" = "unknown" -o "$TERM" = "dialup"  \

                         -o "$TERM" = "network" ]

   then

      eval `ttytype -s -a`

   fi

   export TERM

   if [ "$ERASE" = "" ]

   then

      ERASE="^H"

      export ERASE

   fi

   stty erase $ERASE

   trap "echo logout" 0

   cat /etc/copyright

   if [ -r /etc/motd ]

   then

      cat /etc/motd

   fi

   if [ -f /usr/bin/mail ]

   then

      if mail –e

      then echo "You have mail."

      fi

   fi

   if [ -f /usr/bin/news ]

   then news –n

   fi

   if [ -r /tmp/changetape ]

   then

      echo "\007\nYou are the first to log in since backup:"

      echo "Please change the backup tape.\n"

      rm -f /tmp/changetape

   fi

fi

trap 1 2 3

###################### The End ##########################


#!/usr/bin/sh

############# /.profile ################  


set +u

PATH=/usr/sbin:$PATH:/sbin:/home/root

if [ ! "$VUE" ]; then

   if [ "$TERM" = "" ]

   then

      eval ` tset -s -Q -m ':?hp' `

   else

      eval ` tset -s -Q `

   fi

   stty erase "^H" kill "^U" intr "^C" eof "^D" susp "^Z"

   stty hupcl ixon ixoff

   tabs

   echo

   echo "Value of TERM has been set to \"$TERM\". "

   export TERM

   EDITOR=vi

   export EDITOR

fi

set –u

trap "echo 'logout root'" 0

MAIL=/var/mail/root

echo "WARNING:  YOU ARE SUPERUSER !!\n"

export PS1=`hostname`':$PWD# '

############################# The End ##############################





#!/sbin/sh

######################## /sbin/init.d/inetd #######################

PATH=/sbin:/usr/sbin:/usr/bin

export PATH

rval=0

set_return() {

        x=$?

        if [ $x -ne 0 ]; then

                echo "EXIT CODE: $x"

                rval=1  # always 1 so that 2 can be used for other reasons

        fi

}

case "$1" in

start_msg)

   echo "Start Internet services  daemon" ;;

stop_msg)

   echo "Stopping Internet services daemon" ;;

'start')

   if [ -f /etc/rc.config ]; then

      . /etc/rc.config

   else

      echo "ERROR: /etc/rc.config defaults file MISSING"

   fi

   mask=`umask`

   umask 000

   [ -x /usr/sbin/inetd ] && /usr/sbin/inetd $INETD_ARGS

   if [ $? -eq 0 ]; then

      echo "Internet Services started"

   else

      echo "Unable to start Internet Services"

   fi

   umask $mask

   ;;

'stop')

   if [ -f /etc/rc.config ]; then

      . /etc/rc.config

   else

      echo "ERROR: /etc/rc.config defaults file MISSING"

   fi

   /usr/sbin/inetd -k

   set_return

   if [ $rval -eq 0 ]; then

      echo "Internet Services stopped"

   else

      echo "Unable to stop Internet Services"

   fi

   ;;

*)

   echo "usage: $0 {start|stop}"

   rval=1

   ;;

esac

exit $rval

############################ The End ##############################3

#!/sbin/sh

############# /sbin/rc ################      


arg=$1

arg2=$2

PATH=/sbin

export PATH

/sbin/stty clocal icanon echo opost onlcr ixon icrnl ignpar 2> /dev/null

umask 022

get_scripts() {

   state=$1

   mode=$2

   dir=/sbin/rc${state}.d

   ls $dir 2>/dev/null |

   while read name

   do

      case $name in

      ${mode}*)

         path=$dir/$name

         if [ "$mode" = "S" ]; then

            desc=`$path start_msg`

         elif [ "$mode" = "K" ]; then

            desc=`$path stop_msg`

         fi

         echo $path $desc

     esac

  done

}

if [ -f /sbin/rc.utils ]; then

   . /sbin/rc.utils

else

   init_list()

   {

      echo $1

   }

   add_list()

   {

      eval $1

   }

   run_list()

   {

      :

   }

fi

# If /etc/rc.config contains default information (first boot),

# /sbin/auto_parms will invoke /sbin/set_parms to remedy the situation.

# For 10.0 release, the default HOSTNAME is unset or an empty string.

# Assume a timezone if /etc/TIMEZONE does not exist.

TZ=EST5EDT

if [ -f /etc/rc.config ]; then

   . /etc/rc.config

   if [ -x /sbin/auto_parms ]; then

      /sbin/auto_parms

   else

      echo "\nWARNING: /sbin/auto_parms does not exist"

      echo "DHCP invocation skipped."

   fi

else

   echo "\nWARNING: /etc/rc.config does not exist"

   echo "System name not set, default $TZ assumed."

fi

export TZ

# Set runlevel information

set `who -r` x

new=$7         # new run level

old=$9         # previous run level

# Check to see if we are run from /etc/inittab, or from the command line.

# If run from the command line, set the old run-level to the new run-level.

if [ $PPID != 1 ]; then

   old=$new

   # If the new run-level was specified on the command line,go to that state

   # instead.

   if [[ -n $arg2 ]]; then

      new=$arg2

   fi

fi

if [ "$new" = S ]; then

   new=0

   tosingle=1

else

   tosingle=0

fi

BOOT=0

if [ "$old" = S ]; then

   old=0

   BOOT=1

fi

# Process scripts

found=0

if [ "$new" -gt "$old" ]; then

   # new run level is higher than old, so run start scripts in

   # all intermediate run levels and in new run level.

   if [ $BOOT = 1 ]; then

      init_list "HP-UX Start-up in progress"

   else

      init_list "Transition to run-level $new in progress"

   fi

   typeset -i lvl=$old

   lvl=lvl+1

   while [ $lvl -le "$new" ]; do

      get_scripts $lvl S |

      while read name descrip; do

         if [ -s "$name" ]; then

            add_list "$name start" "$descrip"

            found=1

         fi

      done

      lvl=lvl+1

   done

elif [ "$new" -lt "$old" ]; then

   # new run level is lower than old level, so run kill scripts

   # in all intermediate levels and in new level.

   if [ "$new" = 0 ]; then

      init_list "System shutdown in progress"

   else

      init_list "Transition to run-level $new in progress"

   fi

   typeset -i lvl=$old

   lvl=lvl-1

   while [ $lvl -ge "$new" ]; do

      get_scripts $lvl K |

      while read name descrip; do

         if [ -s "$name" ]; then

            add_list "$name stop" "$descrip"

            found=1

         fi

      done

      lvl=lvl-1

   done

   # If we're ending up in state 0 or S, run the start scripts for

   # that state.

   if [ "$new" = 0 ]; then

      get_scripts 0 S |

      while read name descrip; do

         if [ -s "$name" ]; then

            add_list "$name start" "$descrip"

            found=1

         fi

      done

   fi

else

   # old and new run levels are the same.  Assume that execution

   # is from the command line and run start scripts for the current

   # run level

   init_list "Starting subsystems for run-level $new"

   get_scripts ${new} S |

   while read name descrip; do

      if [ -s "$name" ]; then

         add_list "$name start" "$descrip"

         found=1

      fi

   done

fi

if [ $found = 1 ]; then

   if [ "$BOOT" = 1 ]; then

      run_list boot

   else

      run_list

   fi

fi

if [ "$new" = 0 ]; then

   case $arg in

   "shutdown")

      exec /sbin/sh

      ;;

   "reboot")

      /sbin/reboot

      ;;

   "off")

      /sbin/reboot -h

      ;;

   esac

   #If transitioned to real state 0 (that is, not state S) via init, halt.

   if [[ $PPID -eq 1 && "$tosingle" -ne 1 ]]; then

      /sbin/reboot -h

   fi

fi

# Output message to indicate completion

echo

if [ $BOOT = 1 ]; then

   echo "The system is ready."

else

   echo "Transition to run-level $new is complete."

fi

############################## The End #################################3




















#!/sbin/sh

##################### /sbin/init.d/net ##########################

#

# net:  configure lan interface(s) at initialization time.

# /etc/rc.config.d/netconf defines the configuration parameters:

#

# INTERFACE_NAME[i]:      network interface name (e.g., lan0)

# IP_ADDRESS[i]:          IP address of your system in decimal dot format

# SUBNET_NETMASK[i]:     subnetwork mask in decimal dot format

# BROADCAST_ADDRESS[i]:  broadcast address (other than default) in decimal

#                             format

# LANCONFIG_ARGS[i]:      lanconfig(1m) options (e.g., ieee, ether)

# LOOPBACK_ADDRESS:       loopback address (always 127.0.0.1)

#

# ROUTE_DESTINATION[i]:  route destination

# ROUTE_MASK[i]:       subnet mask

# ROUTE_GATEWAY[i]:       local or remote IP address of gateway

# ROUTE_COUNT[i]:         zero for local gateway, one for remote gateway

# ROUTE_ARGS[i]:          route command options and arguments

#

###########################################################################


set +u  

export PATH=/sbin:/usr/sbin:$PATH

NETCONF=/etc/rc.config.d/netconf

NETSTAT_DATA=/var/adm/netstat_data

OKAY=0

ERROR=1

WARNING=2

# $1 = name of array

# return highest array element index in env; return -1 if no elements

function maxindex {

   # find only lines that start with "var[...]=", grab only the number

   # between "[...]", and print only the last one.

   # we would like to use `sed` as follows:

   #    typeset i=$(set | sed -n 's/^'$1'\[\([[:digit:]]\{1,\}\)\]=.*$/\1/p'

   #                | tail -1)

   # but it is not guaranteed to be in a mounted file system at this time.

   typeset line

   typeset i=-1

   set | while read line; do

      # strip "var[" and "]=...", leaving only number between "[...]"

      line=${line#*$1\[}

      line=${line%%\]=*}

      # if line is all digits, we found "var[...]=...",

      # and line is string between "[...]"

      if [[ -n $line && -z ${line##*([[:digit:]])} ]]; then

         i=$line

      fi

   done

   print -- $i

   return 0

}

##########

#  main   #

##########

case $1 in

start_msg)

   print "Configure LAN interfaces"

   exit $OKAY

   ;;

stop_msg)

   print "Unconfigure LAN interfaces"

   exit $OKAY

   ;;

stop)

   exit $OKAY

   ;;

start)

   ;;  # fall through

*)

   print "USAGE: $0 {start_msg | stop_msg | start | stop}" >&2

   exit $ERROR

   ;;

esac

###########

#  start  #

###########

# Remove the existing /var/adm/netstat_data file.  The first time

# netstat is executed, a new /var/adm/netstat_data file will be

# created.

rm -f $NETSTAT_DATA

# Get actual configuration

if [[ -f $NETCONF ]]; then

   . $NETCONF               # display any errors

   if (($? != 0)); then

      # NB: this is not working as expected:  status is not propagated!

      print "ERROR:   Incorrect data in the file $NETCONF." >&2

      exit $ERROR

   fi

else

   print "ERROR:   Missing the file $NETCONF." >&2

   exit $ERROR

fi

rval=$OKAY

# Do ifconfig and lanconfig commands for each interface

# `foo=$(print $foo)` collapses whitespace, remove surrounding whitespace

# We can have __fewer__ IP_ADDRESSes than INTERFACE_NAMEs (interfaces to be

# ignore).  We can also have __fewer__ SUBNET_MASKs, BROADCAST_ADDRESSes and

# LANCONFIG_ARGS (defaulted).  But we cannot have __more__.

# sanity check

nIF=$(maxindex INTERFACE_NAME)

if (($(maxindex IP_ADDRESS) > nIF)) || \

   (($(maxindex SUBNET_MASK) > nIF)) || \

   (($(maxindex BROADCAST_ADDRESS) > nIF)) || \

   (($(maxindex LANCONFIG_ARGS) > nIF))

then

   print "WARNING: Missing INTERFACE_NAME for corresponding IP_ADDRESS, SUBNET_MASK," >&2

   print "         BROADCAST_ADDRESS or LANCONFIG_ARGS in the file" >&2

   print "         $NETCONF.  Excess variables will be ignored." >&2

   rval=$WARNING

fi

i=0

while ((i <= nIF)); do

   NAME=$(print ${INTERFACE_NAME[i]})

   INTERFACE_NAME[i]=$NAME          # without whitespace for route tests below

   IP=$(print ${IP_ADDRESS[i]})

   IP_ADDRESS[i]=$IP                 # without whitespace for route tests below

   if [[ $IP = "RARP" ]]; then

      IP=`/usr/sbin/rarpc $NAME`

      IP_ADDRESS[i]=$IP              # without whitespace for route tests below

   fi

   if [[ -n $NAME && -n $IP ]]; then

      MASK=$(print ${SUBNET_MASK[i]})

      [[ -n "$MASK" ]] && MASK="netmask $MASK"

      BCAST=$(print ${BROADCAST_ADDRESS[i]})

      [[ -n "$BCAST" ]] && BCAST="broadcast $BCAST"

      PROTO=$(print ${LANCONFIG_ARGS[i]})    # do not set PROTO to any default

      emsg=$(ifconfig $NAME $IP $MASK $BCAST up 2>&1)

      status=$?

      if ((status == 0)) && [[ -n $PROTO ]] ; then

         emsg=$(lanconfig $NAME $PROTO 2>&1)

         status=$?

      fi

      if ((status != 0)); then

         print "ERROR:   $NAME interface: $emsg" >&2

         rval=$ERROR

      fi

   fi

   let i=i+1

done

IP=$(print $LOOPBACK_ADDRESS)

if [[ -n $IP ]]; then

   emsg=$(ifconfig lo0 $IP up 2>&1)

   if (($? != 0)); then

      print "ERROR:   lo0 interface: $emsg" >&2

      rval=$ERROR

   fi

else

   print "ERROR:   Missing LOOPBACK_ADDRESS in the file $NETCONF." >&2

   print "         lo0 interface not initialized." >&2

   rval=$ERROR

fi

# Do route command for each configured route

# Note:  ${IP_ADDRESS[i]} must have whitespace removed already (above)

# We must have the __same__ number of ROUTE_GATEWAYs as ROUTE_DESTINATIONs.

# But we can have __fewer__ ROUTE_COUNTs and ROUTE_MASKs (defaulted).

n=$(maxindex ROUTE_DESTINATION)

if (($(maxindex ROUTE_GATEWAY) != n)) || \

   (($(maxindex ROUTE_COUNT) > n))

then

   print \

      "WARNING: Missing ROUTE_DESTINATION for corresponding ROUTE_GATEWAY" >&2

   print "         or ROUTE_COUNT in the file $NETCONF." >&2

   print "         Excess variables will be ignored." >&2

   rval=$WARNING

fi

i=0

while ((i <= n))

do

   DEST=$(print ${ROUTE_DESTINATION[i]})

   GWAY=$(print ${ROUTE_GATEWAY[i]})

   if [[ -n $DEST && -n $GWAY ]]; then

      COUNT=$(print ${ROUTE_COUNT[i]})

      if [[ -z $COUNT ]]; then

         # default COUNT:  if GWAY is one of the local interface IP

         # addresses, count is 0; otherwise, count is 1.

         COUNT=1

         k=0

         while ((k <= nIF)); do

            if [[ $GWAY = ${IP_ADDRESS[k]} && -n ${INTERFACE_NAME[k]} ]]; then

               COUNT=0

               break;

            fi

            let k=k+1

         done

      fi

      ARGS=${ROUTE_ARGS[i]}

      MASK=$(print ${ROUTE_MASK[i]})

      if [[ -z $MASK ]]; then

          # No subnet mask

          if [[ -z $ARGS ]]; then

             # No arguments

             emsg=$(route add $DEST $GWAY $COUNT 2>&1)

          else

             # With arguments

             emsg=$(route $ARGS add $DEST $GWAY $COUNT 2>&1)

          fi

      else

         # Subnet mask has been entered.

         if [[ -z $ARGS ]]; then

            # No arguments

            emsg=$(route add $DEST netmask $MASK $GWAY $COUNT 2>&1)

         else

            # With arguments

            emsg=$(route $ARGS add $DEST netmask $MASK $GWAY $COUNT 2>&1)

         fi

      fi

      # ignore "entry in use" errors.  these can arise because we

      # booted via NFS diskless, which added routes already

      if (($? != 0)) && [[ -n ${emsg##*entry in use*} ]]; then

         print "ERROR:   $emsg" >&2

         rval=$ERROR

      fi

   fi

   let i=i+1

done

# add loopback route for local interfaces to improve performance

k=0

while ((k <= nIF))

do

   if [[ -n ${IP_ADDRESS[k]} && -n ${INTERFACE_NAME[k]} ]]; then

      emsg=$(route add ${IP_ADDRESS[k]} $LOOPBACK_ADDRESS 0 2>&1)

      if (($? != 0)) && [[ -n ${emsg##*entry in use*} ]]; then

         print "ERROR:   $emsg" >&2

         rval=$ERROR

      fi

   fi

   let k=k+1

done

exit $rval

##################### The End  ###########################





 소개


u      Shell 종류


/usr/bin/sh      POSIX Shell

/usr/bin/ksh     Korn Shell

/usr/old/bin/sh  Bourne Shell

/usr/bin/csh     C Shell

/usr/bin/keysh   Key Shell

/usr/bin/rksh    Restricted Korn Shell

/usr/bin/rsh     Restricted Shell


u      Shell Startup 파일


Korn Shell     /etc/profile -> $HOME/.profile -> $HOME/.kshrc

Bourne Shell   /etc/profile -> $HOME/.profile

POSIX Shell    /etc/profile -> $HOME/.profile -> $HOME/.kshrc

C Shell        $HOME/.login -> $HOME/.cshrc


2.Shell Parameter


u      Parameter Substitution


l         Parameter Setting


# Parameter=Value

# 변수명=값  : Named Parameter


l         Parameter의 Unsetting


# unset parameter

  # unset 변수명

u        Command Substitution


# $(command)       # `command`


# XX="12345"

# echo $XX

12345

# HOST=‘hostname‘

# echo $HOST     : # HOST=`hostname` 문장은 # HOST=$(hostname)과 같다

ssosvr3           : 즉, `command` 문장과 $(command)는 같은 뜻이다

# PS1=‘hostname‘':$PWD# '

# PS1=$(hostname)':$PWD# '; echo $PS1

ssosvr3:/#

# W1="A"; W2="B"; W3="C"

# WORD=${W1}AA${W2}BB${W3}CC

# echo $WORD

AAABBBCCC

# unset WORD

- $10과 ${10}은 다르다. 왜냐하면 $10은 positional parameter $1값에

   0값이 붙여서 출력되며, ${10}은 positional parameter 10번째의 값을

   나타내기 때문이다.


u        Positional Parameter(위치변수)


shell-script  arg1  arg2  arg3  arg4

$0               $1    $2     $3    $4

Positional Parameter : $1,$2,$3,$4

$0          shell script명을 나타낸다

$1          첫번째 argument를 나타낸다. 즉, arg1

$2          두번째 argument를 나타낸다. 즉, arg2

$*          "arg1 arg2 arg3 arg4 ..." 즉,모든 argument와 같다.

$@          "arg1" "arg2" "arg3" "arg4..." 즉,개개의 argument와 같다.

$#          모든 argument의 갯수

$?          마지막으로 수행된 명령어가 return한 값

$$          현재 shell script를 수행하고 있는 shell의 process id(pid)

$!          현재shell에서 수행한 마지막 background의 pid

$_          shell command의 마지막 argument를 가르키며,shell start시에는

            shell의 절대 PATH를 가르킨다.


# set aaa bbb ccc ddd eee fff 

- set명령어를 옵션없이 사용하면 positional parameter를 setting한다.

# echo $0      sh   현재shell를 나타낸다.

# echo $1      aaa

# echo $#      5    $# 은 argument의 개수를 나타낸다.

# echo $*      "aaa bbb ccc ddd eee fff"

# echo $@      "aaa" "bbb" "ccc" "ddd" "eee"

- "$*" 와 "$@" 의 차이점은 $*은 Positional parameter의 모든값을 하나의

  문자열(string)으로 취급하며 $@ 는 string을 개개의 문자열로 취급한다.

# echo $$    7637   : shell의 process id


${parameter}           parameter의 값. 이것은 {}뒤에 붙어있는 문자나

                       숫자,_ 와 같은문자와 함께 사용할 때 필요하다.

${#parameter}          parameter값의 문자수. ${#*}나 ${#@}은 positional

                       parameter의 개수를 나타낸다.

${#identifier[*]}             배열 identifier에서 element의 수를 출력한다.

${parameter:-word}     parameter가 set되고 NOT NULL이면 parameter값을 출력하고,

                       그렇지 않으면 word의 값을 출력한다.

${parameter:+word}     parameter가 set되고 NOT NULL이면 word의 값을 출력하고,

                       그렇지 않으면 아무것도 출력하지 않는다.

${parameter:=word}     parameter가 set되고 NOT NULL이면 parameter의 값을

                       출력하고, 그렇지 않으면 word의 값을 출력하고 parameter에

                       word의 값을 assign한다. Positional parameter는

                       이렇게 setting할 수 없다.

${parameter:?word}     parameter가 set되고 NOT NULL이면 parameter값을

                       출력하고, 그렇지 않으면 word를 출력하고 shell를

                       exit한다. word가 생략되면 화면에 표준출력된다.


# dir1=/home/tmp

# echo ${dir1:-/usr/bin}

/home/tmp

# unset X

# echo ${X:-"X is unset"}

X is unset   : X가 unset또는 null이면 word가 출력된다.

# echo ${dir1:+/usr/bin}

/usr/bin     : dir1이 null이면 아무것도 출력되지 않는다.

# echo ${dir1:=/usr/bin}

/home/tmp    : dir1이 unset되었거나 null이라면 /usr/bin이 출력된다.

# echo ${dir1:?/usr/bin}

/home/tmp

# echo ${#dir1}

10               : /users/tmp 의 총 문자갯수

${parameter#pattern}   pattern이 parameter값의 첫문자와 같으면 그문자를

${parameter##pattern}  포함한 부분은 delete된다. ##은 wild card(*)시 사용함.

   

${parameter%pattern}   pattern이 parameter값을 끝문자와 같으면 그문자를

${parameter%%pattern}  포함한 문자는 delete된다. %%은 wild card(*)시 사용함.


# XX=/a/b/c/d/a/b

# echo ${XX#*a}

/b/c/d/a/b

# echo ${XX##*a}

/b

# echo ${XX%a*}

/a/b/c/d/

# echo ${XX%%a*}

/

# AA="12345123"

# echo ${AA#1}

2345123

# echo ${AA##*1}

23

# echo ${AA%3}

1234512

# echo ${AA%%3*}

12

# echo ${AA#5}

12345123

# echo ${AA##*5}

123

# echo ${AA##*3*}


# echo ${AA##6*}

12345123


u        Tilde(~) Substitution


만약 user mary의 home directory가 /users/mary라면

# echo $HOME

/users/mary

# echo ~           : ~ 는 user의 home directory를 나타낸다.

/users/mary

# echo $PWD

/users/mary/tmp

# ls ~+/x*         : ~ 다음의 + 는 현재directory 즉, $PWD의 값을 가르킨다.

/users/mary/tmp/x_file1

/users/mary/tmp/x_file2

# echo $OLDPWD

/users/mary/mail

# ls ~-/f*         : ~ 뒤의 - 는 이전 directory 즉, $OLDPWD의 값을 가르킨다.

/users/mary/mail/from.mike 

/users/mary/mail/from.nick


u        Shell Command Grouping


l         ( command )  : subshell grouping

                 shell은 마치 또다른 script를 call한것처럼 subshell

                 환경에서 command를 수행한다.

l         { command ;} : brace grouping

                    shell은 현재의 shell 환경에서 연속해서command를

수행하며 마지막에 반드시 ;(세미콜론)을 써야한다.


# vi test1.sh

#! /usr/bin/sh

# (command)의 Example


A="aaa"

B="bbb"

C="ccc"

( A="AAA"

B="BBB"

C="CCC"

echo "PID $$ :

      $A $B $C" )

echo "PID $$ :

       $A $B $C"

:wq

# sh test1.sh

PID 28999 : AAA BBB CCC

PID 28999 : aaa bbb ccc

# vi test2.sh

#! /usr/bin/sh

# {command;}의 Example


A="aaa"

B="bbb"

C="ccc"

{ A="AAA"

B="BBB"

C="CCC"

echo "PID $$ :

      $A $B $C" ;}

echo "PID $$ :

       $A $B $C"

:wq

# sh test2.sh

PID 28955 : AAA BBB CCC

PID 28955 : AAA BBB CCC


u        Shell Script의 수행


# sh shell_script

# ksh shell_script

# chmod 777 shell_script

# ./shell_scipt


u        Shell Script Comment


l         shell script에서 comment는 첫라인에 # symbol를 넣는다.

l         shell script에서 첫라인의 #! /usr/bin/sh의 의미는 이 shell은

    Posix shell로 수행한다는 의미이다.


u        Input and Output


stdin(0)         standard input으로서 default는 keyboard이며

                 file descriptor값은 0 이다.

stdout(1)        standard output으로서 default는 terminal display이다.

                 file descriptor값은 1 이다.

stderr(2)        standard error로서 default는 terminal displsy이다.

                 file descriptor값은 2 이다.

<word            표준입력(file descriptor 0)으로 word를 사용한다.

>word            표준출력(file descriptor 1)으로 word를 사용하며,

word라는 file이 생성된다.

>|word           >word와 같으며 noclobber옵션이 설정되있어도 무조건 overwrite한다.

>>word           word라는 file이 존재하면 file에 append한다.

없으면 word라는file을 생성한다.

<>word           word를 입력으로 받아서 다시 word라는 file로 출력한다.

<<word           shell prompt에서 word라는 글자를 만날때까지 command를 입력할 수

                 있으며 word라는 글자를 만나면 shell command가 수행된다.

<&숫자           file descriptor 숫자의 file에서 data를 입력받는다.

>&숫자           file descriptor숫자를 가진 file로 출력한다.

<&-              표준입력을 close하여 keyboard로부터 입력받지 못한다.

>&-              표준출력을 close하여 terminal로 출력하지 않는다.


# ftp -n -i << AAA

>open mars

>user root password

>cd /users

>mget *

>close

AAA

#


# vi datafile       : data file작성

aaa

bbb

ccc

:wq

# vi read.sh

exec 5< datafile  : datafile을 file descriptor 5번으로 open한다.

read -u5 X        : 첫라인을 read하여 X변수에 assign한다.

read -u5 Y         : 둘째라인을 read하여 Y변수에 할당.

read -u5 Z        : 셋째라인을 read하여 Z변수에 할당.

exec 5<&-         : file descriptor 5번 file을 close한다.

echo "$X $Y $Z"   : file descriptor은 3-9까지 쓸수있다.

:wq

# sh read.sh

aaa bbb ccc






u        조건 표현식


test 또는 [ ... ]             Integer,string.file등에 모두사용(old syntax)

(( ... ))              Integer에만 사용(new syntax)

[[ ... ]]              string,file에만 사용(new syntax)


l         String 표현식  # man test 참조

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

[ -b file ]            file이 존재하고 block special file이면 참

[ -c file ]            file이 존재하고 character special file이면 참

[ -d file ]            file이 존재하고 directory이면 참

[ -e file ]            file이 존재하면 참

[ -f file ]            file이 존재하고 ordinary file이면 참

[ -g file ]            file이 존재하고 setgid bit가 set되있으면 참

[ -h file ]            file이 존재하고 symbolic link되었으면 참

[ -k file ]            file이 존재하고 sticky bit가 set되었으면 참

[ -p file ]            file이 존재하고 fifo special file또는 pipe이면 참

[ -r file ]            file이 존재하고 readable하면 참

[ -s file ]            file이 존재하고 file size가 0보다 크면 참

[ -u file ]            file이 존재하고 setuid bit가 set되 있으면 참

[ -w file ]            file이 존재하고 writable하면 참

[ -x file ]            file이 존재하고 executable하면 참

[ -L file ]            file이 존재하고 symbolic link이면 참

[ -O file ]            file이 존재하고 user가 effective user id와 같으면 참

[ -G file ]            file이 존재하고 group이 effective group id와 같으면 참

[ -S file ]            file이 존재하고 socket이면 참

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

[ -n string ]          string의 길이가 non zero면 참

[ -z string ]          string의 길이가 zero이면 참

[ string ]                    string이 not null string이면참





# if [ -f /etc/rc.config ] ; then

# if [ ! -d /usr/bin ] ; then

# if [ -z "$NODENAME" ] ; then

# if [ -x /usr/dt/bin/dtrc ] ; then

# if [[ -n "$NAME" ]] ; then

# if [[ -s /var/spool/lp/pstatus ]] ; then

# if [[ -r /var/run/mrouted.pid ]] ; then

# if [[ -z "$pid" ]] ; then

# if /usr/sbin/envd ; then

# if /sbin/local_is_root ; then

# if [ "$ARRAYMON_PID" ] ; then

# if [ "$START_OV500" ] ; then


[ file1 -nt file2 ]    file1이 존재하고 file2보다 newer이면 참

[ file1 -ot file2 ]    file1이 존재하고 file2보다 older이면 참

[ file1 -ef file2 ]    file1이 존재하고 file2와 equal file이면 참


# if [ /sbin/init.d/spa –nt /sbin/init.d/set_date ] ; then

# if [ /aaa –ot /bbb ] ; then

# if [ /ccc –ef /ddd ] ; then


[ string1 = string2 ]  string1과 string2가 같으면 true

[ string1 = pattern ]  string1과 pattern이 같으면 true

[ string1 != string2 ] string1과 string2가 같지않으면 true

[ string1 != pattern ] string1과 pattern이 같지않으면 true

[ string1 < string2 ]  string1이 string2보다 작으면 true

[ string1 > string2 ]  string1이 string2보다 크면 true


# if [ "$pid" = "" ] ; then

# if [ X$pid != "X" ] ; then

# if [ $HOST != `hostname` ] ; then

# if [ "$MWASTART" > "1" ] ; then

# if [[ $? = 255 ]] ; then


[ exp1 -eq exp2 ]             exp1과 exp2가 같으면 참(equal)

[ exp1 -ne exp2 ]             exp1과 exp2가 같지 않으면 참(not equal)

[ exp1 -lt exp2 ]             exp1이 exp2보다 작으면 참(less than)

[ exp1 -gt exp2 ]             exp1이 exp2보다 크면 참(greater than)

[ exp1 -le exp2 ]             exp1이 exp2보다 작거나 같으면 참(less than or equal)

[ exp1 -ge exp2 ]             exp1이 exp2보다 크거나 같으면 참(greater than or equal)


# if [ $x –ne 0 ] ; then

# if [ $? –eq 0 ] ; then

# if [ "$RWHOD" –eq 1 ] ; then

# if [[ "$rval" –eq ${EXIT_NA} ]] ; then

# while [ ${CNT} –le ${MAX_NISCHECKS} ] ; then

# if [ $# -ge 0 ] ; then

# if [ "$XX" –gt "$YY" ] ; then

# if [ "$X" –lt 1 ] ; then

# if [ $# -ne 1 ] ; then

# if [ `grep $HOSNAME /etc/mail/sendmail.cw|wc –l` -eq 0 ] ; then


( expression )         expression이 참이면 참

! expression           Binary NOT 연산자

exp –a exp2            Binary AND 연산자, 우선순위가 –o 보다 높음.

exp –o exp2            Binary OR 연산자

exp1 && exp2           exp1과 exp2가 모두 참이면 참

exp1 || exp2           exp1가 참이거나 exp2가 참이면 참


# if [ "$GATED" –eq 0 –a "X$pid" = "X" ] ; then

# if [ "$CRON" –eq 1 –a –x /usr/sbin/cron ] ; then

# if [ "$NIS_DOMAIN" –a –f /usr/bin/domainname ] ; then

# if [ "$NIS_MASTER" –ne 0 –o "$NIS_SLAVE" –ne 0 ] ; then

# if [ "$9" = 'S' ] || [ "$9" –lt '2' ] ; then

# if [ "$VTDAEMON_START" –eq 1 ] && [ -x /usr/sbin/vtdaemon ] ; then

# if [[ -r /usr/sbin/swagentd# ]] && [[ -h /usr/sbin/swagentd ]] ; then

# if [ $status !=2 –o –z "$DOMAIN" –o –z "$SERVER" ] ; then

# if (( status == 0 )) && [[ -n $PROTO ]] ; then


l         Integer 표현식


(( integer1 == integer2 ))    integer1과 integer2가 같으면 참

(( integer1 != integer2 ))    integer1과 integer2가 같지 않으면 참

(( integer1 < integer2 ))           integer1이 integer2보다 작으면 참

(( integer1 > integer2 ))           integer1이 integer2보다 크면 참

(( integer1 <= integer2 ))    integer1이 integer2보다 작거나 같으면 참

(( integer1 >= integer2 ))    integer1이 integer2보다 크거나 같으면 참


# if (( $? != 0 )) ; then

# while ((n>0))

# if ((n<2) || !length(part[2])) ; then

# if ( $1 != mypid ) ; then

# if (( $1 > $2 )) ; then


3.Shell Programming


u        if 조건문


if 조건문

then

   명령어

[elif 조건문

then

   명령어]

[else

   명령어]

fi


if 조건문; then 명령어; [elif 조건문; then 명령어;] [else 명령어;] fi


:wq# vi if1.sh

X=hello

if [ $X = hello ]

then

   echo "Welcome"

else

   echo "Goodbye"

fi

:wq

# sh if1.sh

Welcome

# vi if2.sh

if [ -f temp ]

then

   mv temp temp1

elif [ -f temp1 ]

then

   mv temp1 temp2

fi

:wq

# sh if2.sh


u        case 조건문


case 변수 in

변수값1|변수값2…)

   명령어;;

변수값3|변수값4…)

   명령어;;

*)

   명령어;;

esac





#  vi case.sh

case $1 in

-d|-r)

        rmdir $dir1

        echo "directory removed" ;;

-o)

        echo "option -o" ;;

*)     

        echo "Invalid option,Try again..." ;;

esac

:wq

# chmod 777 case1.sh

# ./case.sh -o

option -o


u        while 반복문


while 조건문

do

   명령어

done


- 다음은 모두 같은 while문이다.


while [ 1 ]

do

  echo "Test"

done

while true

do

  echo "Test"

done

while [ : ]

do

  echo "Test"

done

while :

do

  echo "Test"

done


# vi while1.sh

count=$(who|grep -v root|wc -l)

while [ "$count" -gt 0 ]

do

   echo "Users still logged in..."

   sleep 1

   count=$(who|grep -v root|wc -l)

done

:wq

# sh while1.sh


# vi while2.sh

# /usr/bin/sh

#

print -n "Enter a value : "

read Value

print "Thank You"

count=0

while [ "$count" -lt "$Value" ]

do

   (( count=count + 1 ))

   print "Still sleeping for the $count th time..."

   sleep 2

done

print "End of $0"

:wq

# sh while2.sh


u        for 반복문


for 변수 [in 변수값1,변수값2,…]

do

   명령어

done


# vi for1.sh

for name in $(cut -d -f1 /etc/passwd)

do

   mailx $name < message.txt

   echo "Mail sent to $name"

done

:wq

# sh for1.sh

# vi for2.sh

if [[ ! -d "$1" ]]

then

   exit 1

fi

filename=$(ls $1)

for onefile in $filename

do

   if [[ -f ${1}/$onefile ]]

   then

      ll ${1}/$onefile

   elif [[ -d ${1}/$onefile ]]

   then

      ll -d ${1}/$onefile

   fi

done

:wq

# sh for2.sh /etc







u        until 반복문


until 조건문

do

   명령어

done


# vi until.sh

count=$(who|grep -v root|wc -l)

until [ "$count" -eq 0 ]

do

   echo "Users still logged in..."

   sleep 1

   count=$(who|grep -v root|wc -l)

done

:wq

# sh until.sh


u        select 반복문


select 변수 [in 변수값1,변수값2,…]

do

   명령어

done


- select문은 PS3 prompt를 사용한다. PS3 shell 변수의 기본값은 #? 이다.

- 변수는 변수값1,변수값2,… 등이 할당된다.

- 입력된 변수의 값의 숫자는 REPLY라는 shell변수에 저장된다.

- exit,return,break 등의 명령어로 반복문을 빠져나올수 있다.

- [in 변수값1,변수값2,…]가 없을경우에는 Positional Parameter를 사용한다.


# vi edit.sh         ### Edit the file ###

select menu in $(ls) "Exit" ; do

   case $menu in

     Exit) exit;;

     "") echo "Invalid selection. Try again!";;

     *) cp $menu $menu.bak; vi $menu ;;

   esac ; done

:wq





# vi color.sh

  select color in red blue green

  do

     echo "$color is an $color color"

     echo "$REPLY is a REPLY value"

  done

:wq

# sh color.sh

1)red

2)blue

3)green

#? 1

red is an red color

1 is a PEPLY value

#? 2

blue is an blue color

2 is a REPLY value

#? ^C

#


# vi select.sh

PS3="Enter your choice =>"

select menu in "full backup"

                  "partial backup"

do

 case $menu in

 "full backup")

  fbackup –0uf /dev/rmt/0m –i /stand

  echo "Full backup has begun"

  exit 0;;

 "Partial backup")

fbackup –0uf /dev/rmt/0m -i /opt

echo "Partial Backup has begun"

return;;

 *) echo "$REPLY is an invalid

             option. Try again!";;

 esac

done

:wq

# sh select.sh


# vi nest.sh

  #### Nested Select Command Example ###

#! /usr/bin/sh

PS3="Main Choice by number=>"

select menu in "List Files" "Exit"

do

   case $menu in

   "List Files")

      PS3="Sub Choice by number=>"

      select ls_option in "Short" "Long" "Main"

      do

         case $ls_option in

          "Short") lsf;;

           "Long") ll;;

           "Main")

               PS3="Main Choice by number=>"  ## Restore Prompt

               break 1 ;;  ## exit inner loop

           "") echo "$REPLY is an invalid option. Try again!";;

         esac

      done ;;

   "Exit") exit;;

   "") echo "$REPLY is an invalid option. Try again!";;

   esac

done

:wq

# sh nest.sh





u        Function(함수)


function 함수명

{

  shell script

}

함수명()

{

  shell script

}


- shell script안에 선언할수도 있고 밖에 선언할수도 있다.

- 함수명이나 argument로 called될수 있다.

- 같은 process를 반복적으로 사용할때 유리하며 debugging하기가 쉽다.

- typeset -xf name 으로 함수명을 export하여 global 함수로 선언할수 있다.


# vi func1.sh

function exef

{

   if [ -x $1 ]

   then

      echo "$1 is executable"

   fi

}

for file in `ls`

do

   exef $file

done

:wq

# sh func1.sh


# vi func2.sh

Uppercase()

{

   echo $* | tr "[a-z]""[A-Z"]"

}


print -n "Enter in a string:"

read string

upper_string=$(Uppercase $string)

echo "The uppercase string is: $upper_string"

:wq

# sh func2.sh







# vi func3.sh       : Recursive Fuction

bottom_up

{

   typeset SAVEPWD

   echo "\nDirectory being listed is: $PWD\n"

   lsf

   if [ "$PWD" != "/" ]

   then

      SAVEPWD=$PWD

      cd ..

      bottom_up

      cd $SAVEPWD

   else

      echo "That's the end!"

   fi

}

:wq

# sh func3.sh


u        Array(배열)


- shell script에서 사용할수 있는 배열은 1차원배열이다.

- 배열요소(element)는 최대 512-1024까지 쓸수 있다.

- 배열요소는 [0]부터 [1023]까지 쓸수 있다.

- Array subscript인 [N]에서 N은 integer또는 integer expression을 쓸수 있다.


# X[0]=first

# X[1]=second

# X[2]=third

# echo ${X[1]}

second

# echo ${X}         : ${X}는 ${X[0]}과 같음

first

# echo ${X[*]}             : '*'나 '@'는 모든 요소를 가르킴

first second third

# echo ${#X[*]}

3

# i=3

# X[2*(i+1)]=10

# print ${X[8]

10



# set -A YY 100 200 300    : set -A는 변수를 배열로 선언한다.

# print ${YY[0]} ${YY[1]} ${YY[2]}

100 200 300

# set +A YY 150

# print ${YY[@]}

150 200 300




4.Shell Command


u        : 명령어


- ':' 명령어는 아무것도 수행하지 않으며, 어떤 영향도 미치지 않는다. '0'값이 return됨.


# vi xx.sh

if [ -f /opt ]; then

   ls

else

   :            아무것도 수행하지 않는다.

fi

:wq


u        . 명령어


# . /etc/profile


- /etc/profile이라는 프로그램을 수행한다. 이는 sh나 ksh처럼 또하나의 shell을 fork하여

  프로그램을 수행하지 않으며 이 프로그램은 수행가능한 permission이 없어도 된다.

  즉 이 파일은 'x' permission이 없어도 된다.


u        alias 명령어


alias [-x] [ name[=value] … ]


# alias                             : 현재 setting된 모든 alias를 display

# alias a=alias

# a x=lsf

# alias i='

> echo Users logged in are:

> who|sort

> echo I am `whoami`'

# i                                  : alias문을 수행한다.

# unalias i                        : alias변수 i를 unsetting한다.

# unalias -a                       : shell command에서 typing한 모든

                                        alias를 해제한다.

# alias -x who='who|sort'       : Korn shell에서 who를 export하여

                                        subshell에서도 사용가능하다.


u        break 명령어


break [n]


- for,while,until,select문과 같은 반복문에서 exit할 때 사용한다.

- n을 쓰면 n레벨만큼 loop를 exit한다.


# vi break.sh

for file in x y z none

do

   if [ -x $file ]; then

      echo $file

      break

   fi

done

:wq


u        command 명령어


command [arg …]


- argument를 command로서 취급한다.


# command lsf       : lsf를 command로 사용한다.

# command aaa       : aaa를 command로 사용한다.


u        continue 명령어


continue [n]


- for,while,until,select문과 같은 반복문에서 continue이하의 문을 수행하지 않고

다시 시작한다.

    - n을 쓰면 n번째 반복문을 다시 시작한다.


# vi con.sh

for file in x y z

do

   if [ -x $file ]; then

      continue

      echo "$file is executable"

   fi

   echo $file is not executable

done

:wq


u        echo 명령어


echo [arg …]


# echo 'This is a' $var 'example.'

# echo "This is a $var example."

# echo "Enter your user name: \c"

> read user

> echo 'User is' $user


echo 에서 Escape Character

\b     backspace

\c     continue line. new line을

       하지 않고 계속 붙여서 print한다

\f     form feed

\n     new line

\r     carriage return

\t     tab

\v     vertival tab

\\     backslash


u        eval 명령어


eval [arg …]


- argument를 input으로 받아서 명령어로 수행하며 argument는 command나 shell

  script가 될수 있다.


# cmd='ps -ef > ps.out'

# eval $cmd

# eval "grep jones $file|set|echo $1 $2 $3"


u        exec 명령어


exec [arg …]


- 새로운 process나 subshell을 만들어서 argument를 수행하지 않고 현재 shell로

  명령어를 바로 수행한다.

# exec 3< file          file desciptor number 3으로 file을 open한다.

# ecec 2> /dev/null     표준에러를 /dev/null로 출력한다.


u        expr 명령어         # man expr 참조


expr expression {+,-,\*,/} expression

expr expression {=,\>,\>=,\<,\<=,!=} expression

expr string1 : string2


# a=15

# expr $a + 5

20

# count=`expr $count + 5`

# A=batman

# expr substr $A 1 3

bat

# expr index $A m

4


u        fc 명령어


fc [-r] [-e example] [first [last]]

fc –l [-nr] [first [last]]

fc –s [old=new] [first]

fc –e – [old=new] [command]


- fc command는 history file을 list하거나 history file에서 command를 edit할 수있다.


# fc –l            : history file의 내용을 display한다.

# fc –l 20 25

# fc –l 10

# fc –e vi 15 20

# fc –e -          : 방금 실행한 command를 다시 실행한다. # r 명령과 같다.

# fc –e – ls=cd  


u        let 명령어


let "expression"

(( expression ))

- let는 산술 표현을 가능하게 하며 long integer 계산을 한다.


Operator

Description

-

!

/  %

+  -

<  <=  >  >=

==  !=

=

unary minus

logical negation

곱하기,나누기,몫

더하기,빼기

비교

같다,같지 않다

변수 할당


# x=10

# y=2

# let x=x+2

# echo $x

12

# let "x=x/(y+1)"

# echo $x

4

# (( x=x+1 ))

# echo $x

5

# x=12

# let "x<10"

# echo $?

1

# (( x > 10 ))

# echo $?

0

# if (( x > 10 ))

>then echo x greater

>else echo x not greater

>fi

x greater


u        read 명령어


read [-r] name…        : POSIX Shell only

read [-prsu] [name]    : Korn Shell only


-r          라인연속으로 쓰인 라인끝의 \를 해석하지 않는다.

-un         file descriptor n 으로부터 input을 read한다.


# vi read.sh

  while read -r xx yy

  do

     printf "%s %s \n" "$yy" "$xx"

done < input_file

:wq


u        return 명령어


return [n]


- 함수의 실행을 마치고 calling shell script에게 exit status n을 return한다.

- n이 없으면 return status는 함수의 마지막 command의 값이다.

- return이 함수의 밖에서 수행되면 exit로서 실행된다.


# vi return.sh

  search()

  {

     if grep xxx "$1" > /dev/null 2>&1

     then return 1

     else return 2

     fi

  }

:wq

# sh return.sh filename


u      set 명령어


l         Positional Parameter값 setting


# set spring summer fall winter

# echo $3

fall

# echo $*

spring summer fall winter



l         Positional Parameter Sorting


# set third first second

# echo $1 $2 $3

third first second

# set –s               : 값을 lexical order로 sorting함

# echo $1 $2 $3

first second third

# set +s            : unsetting








option         option-name meaning

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

set –a         allexport   모든 parameter가 자동으로 export됨. == set -o allexport

set -C         noclobber   #date>XX시 >로 overwrite하지못하게 함. date>|XX로는 가능

set –e         errexit     shell command fail시 즉시 logout또는 shell을 exit함

set –f         noglob             # ls * 시wild card문자를 인식못함

set –h         trackall   

set –k         keyword    

set –m         monitor     Background jogs이 각각다른 process group에서 수행되고

                           작업이 끝나면 message를 report함

set –o                     set –o monitor와 같이 option-name에 붙여서 옵션을

                           setting함

set –s                     positional parameter를 sort함

set –t                     shell을 exit한후에 command를 수행함

set –u         nounset     substituting시 unset parameter를 error로 취급함

set –v         verbose     command를 display한후 command 수행

set –x         xtrace             command수행시 command와 argument까지 print함.

                           shell script의 debug mode로 사용함.

              

set                        현재 setting된 모든 shell variable을 list함

set -                      -x와 –v option을 turn off하고 flag에 대한 argument

                           검사를 하지 않음

set --                     옵션의 어떤 변화도 하지못하게 함. # set -- -;echo $1

                                      file명으로 시작하는 file을 rm할 경우 # set -- -;rm –aaa


# set –o ignoreeof          : ignoreeof라는 옵션을 turn on

# set +o vi                : vi의 옵션을 turn off

# set –o noglob            : noglob옵션을 turn on 시키고 wild card인

                                    *,[],-,!,? 등을 shell이 해석하지 못하게함

# set –o noexec            : shell의 syntax error를 check하기위해 사용.

                             이 옵션은 interactive shell에서는 사용되지

                                    않으며 shell script에서만 수행됨.

                             noexec 옵션은 실제로 shell을 수행하지 않으면서

                                       shell의 syntax error만을 check하는 명령어다.



# vi set1.sh

  set –o noexec

  echo "This is test

  ls

  cp /aaa /bbb

:wq

# ksh set1.sh

set1.sh: syntax error at line 2 : '"' unmatched

# vi set2.sh

  set –x

  ls

  echo "The Test"

  set +x

  lsf

:wq

# sh set2.sh


u        shift 명령어


shift [n]


shift command는 positional parameter($1,$2,$3..)의 내용을 왼쪽순으로 move한다.


# vi shift1.sh

  yflag=0

  zopt=""

  for arg in "$@"

  do

     if [ "x$arg" = x-y ]

     then

        yflag=1

        shift

     else

       zopt="$2"

       shift 2

     fi

  done

:wq


u        trap 명령어


trap [command] [signal]


- signal 값은 # kill –l또는 # man kill 명령어로 볼수 있음.

# trap "echo 'Command Failed'" 2

                       : ^C(interupt)를 치면 echo 문장이 수행됨.


# trap              : trap 명령을 수행한후 옵션이 없이 trap명령을 수행하면 현재

                    setting된 모든 trap내용을 보여줌

# trap "" 1 2 3

                       : 1}HUP 2)INT 3)QUIT가 입력되도 무시하라.

# trap "echo logout" 0

                       : signal이 '0' 이면 NULL signal로서

                         shell에서 exit할때 command가 수행된다.


u      typeset 명령어


typeset [-][+]옵션  변수명[=변수값]


option      meaning

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

[-]         변수명의 속성을 setting

[+]         변수명의 속성을 turn off

-Ln         왼쪽의 공백을 제거하고 왼쪽에서 n숫자만큼 cut

-Rn         왼쪽에 공백을 채우고 오른쪽에서 n숫자만큼 cut

-Z          오른쪽으로 shift하고, 첫번째 문자가 숫자이고 –L옵션과 같이

            쓰지 않았으면 왼쪽에 숫자0을 채움

-i          변수명을 integer로 선언

-f          변수명이 아니라 함수명으로 변수를 선언

-l          모든 영문대문자를 소문자로 변환

-u          모든 소문자를 대문자로 변환

-r          변수를 read-only로 만듬,즉 변수를 상수로 만듬

-x          변수를 export함, 즉 변수를 전역변수로 만듬

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

# typeset

현재 setting되어있는 변수의 data type을 보여줌

# typeset AA

AA변수를 string변수로 선언,또한 함수내에서 Local변수 즉 지역변수로 선언

하지만, shell에서 변수는 default로 string data type임


# DATA="Today we had very HOT weather"

# typeset –u DATA

# echo $DATA

TODAY WE HAD VERY HOT WEATHER

# typeset +u DATA : DATA변수의 속성을 turn off 

# DATA="as of the "${DATA}

# echo $DATA

as of the TODAY WE HAD VERY HOT WEATHER


# AAA=123456789

# typeset –L3 AAA

# echo $AAA

123


# typeset –LZ X=00005

# print $X

5

# typeset –i X        : 변수X를  integer로 선언 # integer X와 같음

# typeset –i2 X     : 변수X를 2진수로 선언

# typeset –i8 X     : 변수X를 8진수로 선언

# typeset –i10 X    : 변수X를 10진수로 선언

# typeset –i16 X    : 변수X를 16진수로 선언

# typeset -r Y=123  : 변수Y를 readonly변수로 선언 # readonly Y=123과 같음

# typeset -f        : 모든함수와 그 값을 display함

# typeset -xf       : export된 모든함수와 그 값을 display함

# typeset -xf XX    : 함수명 XX를 export하여 global function으로 선언함


u        ulimit 명령어


ulimit  [-f] [n]


- ulimit command는 child process나 subprocess에 의해 사용된는 resources를 제한한다.


# ulimit               : 현재 limit값을 보여준다

# ulimit –f 1000       : 현재process나 향후 process가 write할 수 있는

                          file size를 1000 block(1000*512 byte)으로 제한한다.

# ulimit –f unlimited : child process가 생성할 수 있는 size의 제한을 없앤다.







5.Regular Expression(정규 수식)


u        Pattern Matching과 Regular Expression의 비교 - # man 5 regexp참조


Pattern Matching


Regular Expression

- POSIX shell에서 사용

- file name생성과 case문에서 사용

- UNIX command와 Text Editor에서 사용

  (ed,vi,ex,sed,awk,expr,grep)

- file name을 match한다

- character string을 match한다

- file name을 substitute한다

- string을 search해서 substitute한다

- 사용되는 특수문자

  ?,  *,  [ - ],  !

- 사용되는 특수문자

  .,  [],  -,  ^,  $,  *


u        하나의 문자와 Match - .(dot)


A.          : AB,Ab,AA,A9등과 같이 A다음에오는 어느한문자와 match

...         : 연속된 3문자와 match

# man 5 regexp|col -b|expand > regexp.man

# grep 'RE.' regexp.man       : RE다음에오는 어느한문자와 Match되는 라인만 출력


u        문자의 시작과 Match - ^


^abc        : 첫문자가 abc로 시작되는 문자와 match. abc,abcabc,abcdef등과 match

^C          : 문자의 시작에서 C와 match

^C$         : 하나의 문자 C와 match

^.$         : 하나의 문자로만 구성된 문자와 match

^[ABC]      : 첫문자가 ABC로 시작되는 문자와 match


u        문자의 끝과 Match - $


abc$        : 끝문자가 abc로 끝나는 문자와 match. defgabc,cccabc,abc등과 match

^...$       : 3개의 문자로만 구성된 문자와 match

\.$         : 문자의 끝에서 마침표(.)과 match

\*$         : 문자의 끝에서 (*)와 match



u        문자 Match - []


[Tt]he      : The나 the라는 글자를 search

h[iau]t     : hit,hat,hut의 글자와 match

[ABC]       : A,B,C를 포함하는 문자와 match


u        범위를 포함하는 문자와 Match - [ - ]


[a-z]       : 소문자 a부터 z까지 어느문자와도 match

[0-9]        : 0-9까지 어떤 하나의 숫자와 match

[0-57]      : 0,1,2,3,4,5,7과 match

[a-c5-8X-Z] : a,b,c,5,6,7,8,X,Y,Z중 하나의 문자와 match

[0-3-]      : 0,1,2,3,-와 match


u        Complemented문자 Match - [^  ]


[^ ]        : 공백이 아닌 한문자와 match

[^0-9]      : 0-9까지 숫자가 아닌 하나의 모든문자와 match

[^a-zA-Z]   : 영문 알파벳이 아닌 문자나 숫자와 match

[012^]      : 0,1,2,^와 match

^[^a-z]$    : 소문자을 제외한 나머지 문자중 하나와 match

# man 5 regexp|col -b|expand > regexp.man

# grep '^$' regexp.man|wc -l         : 공백라인수를 출력한다.

# TMOUNT=`/sbin/mount | grep '^/tmp(/| )' | wc -l`

# grep -q -e "^/usr/bin$" -e "^/usr/bin:" -e ":/usr/bin:"\

         -e ":/usr/bin$" /etc/PATH


u        Null 또는 여러 같은문자와 Match - *,+,?


B*          : Null문자,B,BB,BBB...등과 match

AB*C        : AC,ABC,ABBC...등과 match

A+          : A,AA,AAA...등과 match

AB+C        : ABC,ABBC,ABBBC...등과 match

A?          : Null문자 또는 A와 match

AB?C        : AC,ABC와 match

[A-Z]+      : 하나이상의 대문자와 match

(AB)        : AB문자와 match

(AB)+C      : ABC,ABABC,ABABABC...등과 match

AB.*XYZ     : ABXYZ,ABCXYZ,ABCCCCXYZ...등과 match


u        특수문자 Match - \


\*          : 특수문자 *와 match

\$          : 특수문자 $와 match

\\          : 특수문자 \와 match

\\\\\.\*$   : 문자의 끝에서 \\.* 와 match


u        Subexpression - \( ... \)


- \(...\)구문을 사용한다.

- subexpression과 match하는 문자를 recall하기위해 '\숫자'를 사용한다.

- '\숫자' 는 1-9까지 쓸수있다.

- \1 은 1번째 subexpression,\2 는 2번째 subexpression을 나타낸다.


# who

root       console      Oct 23 13:01

root       ttyp1        Oct 27 12:45

root       pts/0        Oct 22 09:03

# who|sed 's/\([^ ][^ ]*\)[^A-Z][^A-Z]*\(.*\)/\2-->\1/'

Oct 23 13:01-->root

Oct 27 12:45-->root

Oct 22 09:03-->root

- 첫번째 /\([^ ][^ ]*\) 는 공백이 아닌 하나이상의 문자와 match하며 뒷부분의

  \1 의 값과 같다.즉, 여기서는 username root를 가르킨다.

- 두번째 \(.*\) 는 최초로 대문자로 시작되는 문자와 match하며 뒷부분의

  \2 의 값과 같다. 여기서는 Oct를 가르킨다.



6.Sed(Stream Editor)


u        sed 형식


sed [-n] command input_file...

sed [-n] [-e command]... [-f script_file]... [input_file...]


-n          화면에 display하지 않는다. 단  p명령어일경우는 화면에 display한다.

            -n옵션은 -e나 -f옵션중 하나와 같이 사용할수 있다.

-e command  command를 editing하며, input file이 없으면 표준입력이 사용된다.

-f script   input file에서 editing command의 script file을 수행한다.


- sed는 입력파일로부터 한라인씩 data를 read한다.

- sed는 default로 화면에 출력을 하며 input file을 modify하지 않는다.


# sed "s/UNIX/Unix/g" file1 > file2.new

# sed -e "s/Miss/Ms/g" -e "s/Mrs/Ms/g" file2

# sed -n "1,10p" file2

# cat script

1,10p

# sed -n -f script file2


u        s(substitute)


[address [,address]] s/string_old/string_new/[flag]


flag        meaning

g           global substitution(전라인을 모두바꾼다)

p           print line

w file      file로 write한다


# sed "s/[Cc]omputer/COMPUTER/g" file1

# sed -e "1,5s/abc/xyz/" -e 's/kbs/mbc/' file1 > file2

# sed "/abcde/s/ab/AB/g" file1

# sed -e 's/abc/xyz/w file2' file1

# sed "3s/the/xyz/g" file1

# sed '3s/^the /xyz/' file1

# sed -e "/the/s/ for /xyz/g

# cat file1| sed "/the/s/ for /xyz/gw file2

# sed "1,8s/aaa/bbb/g" file1 > file2

# sed "/^5/,/^15/s/from/FROM/g"

# sed -e "/^The first time/,/^End of file/s/lsf/ll/g"

# sed "1,$s/\/usr\/bin/\/sbin\/bin/g"


u        d(delete)


# sed "1,10d" fileA

   - fileA에서 1-10라인까지 delete한다.

# sed "/^From/!d" mbox

   - mbox file에서 From으로 시작되는 라인만 제외하고 모두 delete한다.


u        p(print),l(list),=,q(quit),r(read),w(write)


p           standard output에 print한다. -n옵션과 함께써도 print된다.

l           nonprinting문자도 같이 표준출력한다.

=           address 라인의 라인번호를 표준출력한다.

q           현재라인을 출력하고 sed를 종료한다.

r file      file의 내용을 read하여 표준출력한다.

w file      file에 address라인을 write또는 append한다.


# vi cap

   One potato, teo potato,

   three potato, four.

   Five potato, six potato,

   seven potato, more.

:wq


# sed -n "1,2p" cap

One potato, two potato,

three potato, four.


# sed -e "q" cap

One potato, teo potato,

# sed -e "/\./=" -e " /[A-Z]/w file1" cap

One potato, teo potato,

2

three potato, four.

Five potato, six potato,

4

seven potato, more.


# killproc() {

      for x in "$@"

      do

         pid=`ps -e |grep "$x" |sed -e 's/^  *//' -e 's/ .*//'`

         [ ! –z "$pid" ] && echo killing $x && kill $pid &

      done

  }

# findproc() {

    pid=`ps –e |grep "$1" |sed -e 's/^  *//' -e 's/ .*//'`

    echo $pid

  }

# killproc() {           

      echo stopping $1

      pid=`/usr/bin/ps -e |

            /usr/bin/grep "$1" |

            /usr/bin/sed -e 's/^  *//' -e 's/ .*//'`

            [ "$pid" != "" ] && kill $pid

  }

# if [ "$RWHOD" –ne 1 ]; then

      rval=2

  else

      pid=`ps -el | awk '( ($NF ~ /rwhod/) && ($4 != mypid) &&

           ($5 != mypid)) { print $4 }' mypid=$$ `

      if [ "X$pid" != "X" ]; then

         if kill $pid; then

            echo "rwhod stopped"

         else

            rval=1

            echo "Unable to stop rwhod"

         fi

      fi

  fi

#

#

#

# ARRAYMON_PID=`ps -ef | awk '$0 ~ /.*arraymon*/ && $0 !~ /.*awk.*/

                  { print $2 }'`

  if [ "$ARRAYMON_PID" ]

  then

     echo "Killing disk array monitor daemon."

     kill -9 $ARRAYMON_PID

     sleep 2

     ARRAYMON_PID=`ps -ef | awk '$0 ~ /.*arraymon*/ && $0 !~ /.*awk.*/

                     { print $2 }'`

     if [ "$ARRAYMON_PID" ]

     then

       echo "ERROR:  Could not kill ${ARRAY_MONITOR_DAEMON}"

     fi

  fi

#




























7.Shell Program 예제


-shell script를 위한 data file은 다음과 같다.

# vi data

  100 200 300 400

  500 600 700 800

  900 1000 1100 1200

  1300 1400 1500 1600

  1200 800 400 0

:wq

# vi exp1.sh

if [[ ! -f "$1" ]]

then

   echo "${0##*/}"

   exit 1

else

   filename=$1

fi

exec 3< $filename : file descriptor 3으로 filename를 open

typeset -i II=0   : XX를 integer로 선언

while read -u3 AA[0] AA[[1] AA[2] AA[3]

do

   for II in 0 1 2 3

   do

      (( total[II]=${total[II]} + ${AA[II]} ))

   done

print "Subtotal : "

print ${total[*]}

done

print "Total for the four columns are : "

print ${total[@]}

:wq

# sh exp1.sh












#!/usr/bin/sh

######################## /etc/profile ##########################  


trap "" 1 2 3                   

PATH=/usr/bin:/usr/ccs/bin:/usr/contrib/bin

MANPATH=/usr/share/man:/usr/contrib/man:/usr/local/man

if [ ! -d /usr/sbin ]

then

   PATH=$PATH:/sbin

else

   if [ -r /etc/PATH ]

   then

      grep -q -e "^/usr/bin$" -e "^/usr/bin:" -e ":/usr/bin:"\

                -e ":/usr/bin$" /etc/PATH

      if [ $? -eq 0 ]

      then

         PATH=`cat /etc/PATH`

      else

         PATH=$PATH:`cat /etc/PATH`

      fi

   fi

fi

export PATH

if [ -r /etc/MANPATH ]

then

   MANPATH=`cat /etc/MANPATH`

fi

export MANPATH

if [ -r /etc/TIMEZONE ]

then

   . /etc/TIMEZONE 

else

   TZ=MST7MDT       

   export TZ

fi

if [ ! "$VUE" ]; then

   if [ "$TERM" = "" -o "$TERM" = "unknown" -o "$TERM" = "dialup"  \

                         -o "$TERM" = "network" ]

   then

      eval `ttytype -s -a`

   fi

   export TERM

   if [ "$ERASE" = "" ]

   then

      ERASE="^H"

      export ERASE

   fi

   stty erase $ERASE

   trap "echo logout" 0

   cat /etc/copyright

   if [ -r /etc/motd ]

   then

      cat /etc/motd

   fi

   if [ -f /usr/bin/mail ]

   then

      if mail –e

      then echo "You have mail."

      fi

   fi

   if [ -f /usr/bin/news ]

   then news –n

   fi

   if [ -r /tmp/changetape ]

   then

      echo "\007\nYou are the first to log in since backup:"

      echo "Please change the backup tape.\n"

      rm -f /tmp/changetape

   fi

fi

trap 1 2 3

###################### The End ##########################


#!/usr/bin/sh

############# /.profile ################  


set +u

PATH=/usr/sbin:$PATH:/sbin:/home/root

if [ ! "$VUE" ]; then

   if [ "$TERM" = "" ]

   then

      eval ` tset -s -Q -m ':?hp' `

   else

      eval ` tset -s -Q `

   fi

   stty erase "^H" kill "^U" intr "^C" eof "^D" susp "^Z"

   stty hupcl ixon ixoff

   tabs

   echo

   echo "Value of TERM has been set to \"$TERM\". "

   export TERM

   EDITOR=vi

   export EDITOR

fi

set –u

trap "echo 'logout root'" 0

MAIL=/var/mail/root

echo "WARNING:  YOU ARE SUPERUSER !!\n"

export PS1=`hostname`':$PWD# '

############################# The End ##############################





#!/sbin/sh

######################## /sbin/init.d/inetd #######################

PATH=/sbin:/usr/sbin:/usr/bin

export PATH

rval=0

set_return() {

        x=$?

        if [ $x -ne 0 ]; then

                echo "EXIT CODE: $x"

                rval=1  # always 1 so that 2 can be used for other reasons

        fi

}

case "$1" in

start_msg)

   echo "Start Internet services  daemon" ;;

stop_msg)

   echo "Stopping Internet services daemon" ;;

'start')

   if [ -f /etc/rc.config ]; then

      . /etc/rc.config

   else

      echo "ERROR: /etc/rc.config defaults file MISSING"

   fi

   mask=`umask`

   umask 000

   [ -x /usr/sbin/inetd ] && /usr/sbin/inetd $INETD_ARGS

   if [ $? -eq 0 ]; then

      echo "Internet Services started"

   else

      echo "Unable to start Internet Services"

   fi

   umask $mask

   ;;

'stop')

   if [ -f /etc/rc.config ]; then

      . /etc/rc.config

   else

      echo "ERROR: /etc/rc.config defaults file MISSING"

   fi

   /usr/sbin/inetd -k

   set_return

   if [ $rval -eq 0 ]; then

      echo "Internet Services stopped"

   else

      echo "Unable to stop Internet Services"

   fi

   ;;

*)

   echo "usage: $0 {start|stop}"

   rval=1

   ;;

esac

exit $rval

############################ The End ##############################3

#!/sbin/sh

############# /sbin/rc ################      


arg=$1

arg2=$2

PATH=/sbin

export PATH

/sbin/stty clocal icanon echo opost onlcr ixon icrnl ignpar 2> /dev/null

umask 022

get_scripts() {

   state=$1

   mode=$2

   dir=/sbin/rc${state}.d

   ls $dir 2>/dev/null |

   while read name

   do

      case $name in

      ${mode}*)

         path=$dir/$name

         if [ "$mode" = "S" ]; then

            desc=`$path start_msg`

         elif [ "$mode" = "K" ]; then

            desc=`$path stop_msg`

         fi

         echo $path $desc

     esac

  done

}

if [ -f /sbin/rc.utils ]; then

   . /sbin/rc.utils

else

   init_list()

   {

      echo $1

   }

   add_list()

   {

      eval $1

   }

   run_list()

   {

      :

   }

fi

# If /etc/rc.config contains default information (first boot),

# /sbin/auto_parms will invoke /sbin/set_parms to remedy the situation.

# For 10.0 release, the default HOSTNAME is unset or an empty string.

# Assume a timezone if /etc/TIMEZONE does not exist.

TZ=EST5EDT

if [ -f /etc/rc.config ]; then

   . /etc/rc.config

   if [ -x /sbin/auto_parms ]; then

      /sbin/auto_parms

   else

      echo "\nWARNING: /sbin/auto_parms does not exist"

      echo "DHCP invocation skipped."

   fi

else

   echo "\nWARNING: /etc/rc.config does not exist"

   echo "System name not set, default $TZ assumed."

fi

export TZ

# Set runlevel information

set `who -r` x

new=$7         # new run level

old=$9         # previous run level

# Check to see if we are run from /etc/inittab, or from the command line.

# If run from the command line, set the old run-level to the new run-level.

if [ $PPID != 1 ]; then

   old=$new

   # If the new run-level was specified on the command line,go to that state

   # instead.

   if [[ -n $arg2 ]]; then

      new=$arg2

   fi

fi

if [ "$new" = S ]; then

   new=0

   tosingle=1

else

   tosingle=0

fi

BOOT=0

if [ "$old" = S ]; then

   old=0

   BOOT=1

fi

# Process scripts

found=0

if [ "$new" -gt "$old" ]; then

   # new run level is higher than old, so run start scripts in

   # all intermediate run levels and in new run level.

   if [ $BOOT = 1 ]; then

      init_list "HP-UX Start-up in progress"

   else

      init_list "Transition to run-level $new in progress"

   fi

   typeset -i lvl=$old

   lvl=lvl+1

   while [ $lvl -le "$new" ]; do

      get_scripts $lvl S |

      while read name descrip; do

         if [ -s "$name" ]; then

            add_list "$name start" "$descrip"

            found=1

         fi

      done

      lvl=lvl+1

   done

elif [ "$new" -lt "$old" ]; then

   # new run level is lower than old level, so run kill scripts

   # in all intermediate levels and in new level.

   if [ "$new" = 0 ]; then

      init_list "System shutdown in progress"

   else

      init_list "Transition to run-level $new in progress"

   fi

   typeset -i lvl=$old

   lvl=lvl-1

   while [ $lvl -ge "$new" ]; do

      get_scripts $lvl K |

      while read name descrip; do

         if [ -s "$name" ]; then

            add_list "$name stop" "$descrip"

            found=1

         fi

      done

      lvl=lvl-1

   done

   # If we're ending up in state 0 or S, run the start scripts for

   # that state.

   if [ "$new" = 0 ]; then

      get_scripts 0 S |

      while read name descrip; do

         if [ -s "$name" ]; then

            add_list "$name start" "$descrip"

            found=1

         fi

      done

   fi

else

   # old and new run levels are the same.  Assume that execution

   # is from the command line and run start scripts for the current

   # run level

   init_list "Starting subsystems for run-level $new"

   get_scripts ${new} S |

   while read name descrip; do

      if [ -s "$name" ]; then

         add_list "$name start" "$descrip"

         found=1

      fi

   done

fi

if [ $found = 1 ]; then

   if [ "$BOOT" = 1 ]; then

      run_list boot

   else

      run_list

   fi

fi

if [ "$new" = 0 ]; then

   case $arg in

   "shutdown")

      exec /sbin/sh

      ;;

   "reboot")

      /sbin/reboot

      ;;

   "off")

      /sbin/reboot -h

      ;;

   esac

   #If transitioned to real state 0 (that is, not state S) via init, halt.

   if [[ $PPID -eq 1 && "$tosingle" -ne 1 ]]; then

      /sbin/reboot -h

   fi

fi

# Output message to indicate completion

echo

if [ $BOOT = 1 ]; then

   echo "The system is ready."

else

   echo "Transition to run-level $new is complete."

fi

############################## The End #################################3




















#!/sbin/sh

##################### /sbin/init.d/net ##########################

#

# net:  configure lan interface(s) at initialization time.

# /etc/rc.config.d/netconf defines the configuration parameters:

#

# INTERFACE_NAME[i]:      network interface name (e.g., lan0)

# IP_ADDRESS[i]:          IP address of your system in decimal dot format

# SUBNET_NETMASK[i]:     subnetwork mask in decimal dot format

# BROADCAST_ADDRESS[i]:  broadcast address (other than default) in decimal

#                             format

# LANCONFIG_ARGS[i]:      lanconfig(1m) options (e.g., ieee, ether)

# LOOPBACK_ADDRESS:       loopback address (always 127.0.0.1)

#

# ROUTE_DESTINATION[i]:  route destination

# ROUTE_MASK[i]:       subnet mask

# ROUTE_GATEWAY[i]:       local or remote IP address of gateway

# ROUTE_COUNT[i]:         zero for local gateway, one for remote gateway

# ROUTE_ARGS[i]:          route command options and arguments

#

###########################################################################


set +u  

export PATH=/sbin:/usr/sbin:$PATH

NETCONF=/etc/rc.config.d/netconf

NETSTAT_DATA=/var/adm/netstat_data

OKAY=0

ERROR=1

WARNING=2

# $1 = name of array

# return highest array element index in env; return -1 if no elements

function maxindex {

   # find only lines that start with "var[...]=", grab only the number

   # between "[...]", and print only the last one.

   # we would like to use `sed` as follows:

   #    typeset i=$(set | sed -n 's/^'$1'\[\([[:digit:]]\{1,\}\)\]=.*$/\1/p'

   #                | tail -1)

   # but it is not guaranteed to be in a mounted file system at this time.

   typeset line

   typeset i=-1

   set | while read line; do

      # strip "var[" and "]=...", leaving only number between "[...]"

      line=${line#*$1\[}

      line=${line%%\]=*}

      # if line is all digits, we found "var[...]=...",

      # and line is string between "[...]"

      if [[ -n $line && -z ${line##*([[:digit:]])} ]]; then

         i=$line

      fi

   done

   print -- $i

   return 0

}

##########

#  main   #

##########

case $1 in

start_msg)

   print "Configure LAN interfaces"

   exit $OKAY

   ;;

stop_msg)

   print "Unconfigure LAN interfaces"

   exit $OKAY

   ;;

stop)

   exit $OKAY

   ;;

start)

   ;;  # fall through

*)

   print "USAGE: $0 {start_msg | stop_msg | start | stop}" >&2

   exit $ERROR

   ;;

esac

###########

#  start  #

###########

# Remove the existing /var/adm/netstat_data file.  The first time

# netstat is executed, a new /var/adm/netstat_data file will be

# created.

rm -f $NETSTAT_DATA

# Get actual configuration

if [[ -f $NETCONF ]]; then

   . $NETCONF               # display any errors

   if (($? != 0)); then

      # NB: this is not working as expected:  status is not propagated!

      print "ERROR:   Incorrect data in the file $NETCONF." >&2

      exit $ERROR

   fi

else

   print "ERROR:   Missing the file $NETCONF." >&2

   exit $ERROR

fi

rval=$OKAY

# Do ifconfig and lanconfig commands for each interface

# `foo=$(print $foo)` collapses whitespace, remove surrounding whitespace

# We can have __fewer__ IP_ADDRESSes than INTERFACE_NAMEs (interfaces to be

# ignore).  We can also have __fewer__ SUBNET_MASKs, BROADCAST_ADDRESSes and

# LANCONFIG_ARGS (defaulted).  But we cannot have __more__.

# sanity check

nIF=$(maxindex INTERFACE_NAME)

if (($(maxindex IP_ADDRESS) > nIF)) || \

   (($(maxindex SUBNET_MASK) > nIF)) || \

   (($(maxindex BROADCAST_ADDRESS) > nIF)) || \

   (($(maxindex LANCONFIG_ARGS) > nIF))

then

   print "WARNING: Missing INTERFACE_NAME for corresponding IP_ADDRESS, SUBNET_MASK," >&2

   print "         BROADCAST_ADDRESS or LANCONFIG_ARGS in the file" >&2

   print "         $NETCONF.  Excess variables will be ignored." >&2

   rval=$WARNING

fi

i=0

while ((i <= nIF)); do

   NAME=$(print ${INTERFACE_NAME[i]})

   INTERFACE_NAME[i]=$NAME          # without whitespace for route tests below

   IP=$(print ${IP_ADDRESS[i]})

   IP_ADDRESS[i]=$IP                 # without whitespace for route tests below

   if [[ $IP = "RARP" ]]; then

      IP=`/usr/sbin/rarpc $NAME`

      IP_ADDRESS[i]=$IP              # without whitespace for route tests below

   fi

   if [[ -n $NAME && -n $IP ]]; then

      MASK=$(print ${SUBNET_MASK[i]})

      [[ -n "$MASK" ]] && MASK="netmask $MASK"

      BCAST=$(print ${BROADCAST_ADDRESS[i]})

      [[ -n "$BCAST" ]] && BCAST="broadcast $BCAST"

      PROTO=$(print ${LANCONFIG_ARGS[i]})    # do not set PROTO to any default

      emsg=$(ifconfig $NAME $IP $MASK $BCAST up 2>&1)

      status=$?

      if ((status == 0)) && [[ -n $PROTO ]] ; then

         emsg=$(lanconfig $NAME $PROTO 2>&1)

         status=$?

      fi

      if ((status != 0)); then

         print "ERROR:   $NAME interface: $emsg" >&2

         rval=$ERROR

      fi

   fi

   let i=i+1

done

IP=$(print $LOOPBACK_ADDRESS)

if [[ -n $IP ]]; then

   emsg=$(ifconfig lo0 $IP up 2>&1)

   if (($? != 0)); then

      print "ERROR:   lo0 interface: $emsg" >&2

      rval=$ERROR

   fi

else

   print "ERROR:   Missing LOOPBACK_ADDRESS in the file $NETCONF." >&2

   print "         lo0 interface not initialized." >&2

   rval=$ERROR

fi

# Do route command for each configured route

# Note:  ${IP_ADDRESS[i]} must have whitespace removed already (above)

# We must have the __same__ number of ROUTE_GATEWAYs as ROUTE_DESTINATIONs.

# But we can have __fewer__ ROUTE_COUNTs and ROUTE_MASKs (defaulted).

n=$(maxindex ROUTE_DESTINATION)

if (($(maxindex ROUTE_GATEWAY) != n)) || \

   (($(maxindex ROUTE_COUNT) > n))

then

   print \

      "WARNING: Missing ROUTE_DESTINATION for corresponding ROUTE_GATEWAY" >&2

   print "         or ROUTE_COUNT in the file $NETCONF." >&2

   print "         Excess variables will be ignored." >&2

   rval=$WARNING

fi

i=0

while ((i <= n))

do

   DEST=$(print ${ROUTE_DESTINATION[i]})

   GWAY=$(print ${ROUTE_GATEWAY[i]})

   if [[ -n $DEST && -n $GWAY ]]; then

      COUNT=$(print ${ROUTE_COUNT[i]})

      if [[ -z $COUNT ]]; then

         # default COUNT:  if GWAY is one of the local interface IP

         # addresses, count is 0; otherwise, count is 1.

         COUNT=1

         k=0

         while ((k <= nIF)); do

            if [[ $GWAY = ${IP_ADDRESS[k]} && -n ${INTERFACE_NAME[k]} ]]; then

               COUNT=0

               break;

            fi

            let k=k+1

         done

      fi

      ARGS=${ROUTE_ARGS[i]}

      MASK=$(print ${ROUTE_MASK[i]})

      if [[ -z $MASK ]]; then

          # No subnet mask

          if [[ -z $ARGS ]]; then

             # No arguments

             emsg=$(route add $DEST $GWAY $COUNT 2>&1)

          else

             # With arguments

             emsg=$(route $ARGS add $DEST $GWAY $COUNT 2>&1)

          fi

      else

         # Subnet mask has been entered.

         if [[ -z $ARGS ]]; then

            # No arguments

            emsg=$(route add $DEST netmask $MASK $GWAY $COUNT 2>&1)

         else

            # With arguments

            emsg=$(route $ARGS add $DEST netmask $MASK $GWAY $COUNT 2>&1)

         fi

      fi

      # ignore "entry in use" errors.  these can arise because we

      # booted via NFS diskless, which added routes already

      if (($? != 0)) && [[ -n ${emsg##*entry in use*} ]]; then

         print "ERROR:   $emsg" >&2

         rval=$ERROR

      fi

   fi

   let i=i+1

done

# add loopback route for local interfaces to improve performance

k=0

while ((k <= nIF))

do

   if [[ -n ${IP_ADDRESS[k]} && -n ${INTERFACE_NAME[k]} ]]; then

      emsg=$(route add ${IP_ADDRESS[k]} $LOOPBACK_ADDRESS 0 2>&1)

      if (($? != 0)) && [[ -n ${emsg##*entry in use*} ]]; then

         print "ERROR:   $emsg" >&2

         rval=$ERROR

      fi

   fi

   let k=k+1

done

exit $rval

##################### The End  ###########################

1. Shell Program 소개


u      Shell 종류


/usr/bin/sh      POSIX Shell

/usr/bin/ksh     Korn Shell

/usr/old/bin/sh  Bourne Shell

/usr/bin/csh     C Shell

/usr/bin/keysh   Key Shell

/usr/bin/rksh    Restricted Korn Shell

/usr/bin/rsh     Restricted Shell


u      Shell Startup 파일


Korn Shell     /etc/profile -> $HOME/.profile -> $HOME/.kshrc

Bourne Shell   /etc/profile -> $HOME/.profile

POSIX Shell    /etc/profile -> $HOME/.profile -> $HOME/.kshrc

C Shell        $HOME/.login -> $HOME/.cshrc


2.Shell Parameter


u      Parameter Substitution


l         Parameter Setting


# Parameter=Value

# 변수명=값  : Named Parameter


l         Parameter의 Unsetting


# unset parameter

  # unset 변수명

u        Command Substitution


# $(command)       # `command`


# XX="12345"

# echo $XX

12345

# HOST=‘hostname‘

# echo $HOST     : # HOST=`hostname` 문장은 # HOST=$(hostname)과 같다

ssosvr3           : 즉, `command` 문장과 $(command)는 같은 뜻이다

# PS1=‘hostname‘':$PWD# '

# PS1=$(hostname)':$PWD# '; echo $PS1

ssosvr3:/#

# W1="A"; W2="B"; W3="C"

# WORD=${W1}AA${W2}BB${W3}CC

# echo $WORD

AAABBBCCC

# unset WORD

- $10과 ${10}은 다르다. 왜냐하면 $10은 positional parameter $1값에

   0값이 붙여서 출력되며, ${10}은 positional parameter 10번째의 값을

   나타내기 때문이다.


u        Positional Parameter(위치변수)


shell-script  arg1  arg2  arg3  arg4

$0               $1    $2     $3    $4

Positional Parameter : $1,$2,$3,$4

$0          shell script명을 나타낸다

$1          첫번째 argument를 나타낸다. 즉, arg1

$2          두번째 argument를 나타낸다. 즉, arg2

$*          "arg1 arg2 arg3 arg4 ..." 즉,모든 argument와 같다.

$@          "arg1" "arg2" "arg3" "arg4..." 즉,개개의 argument와 같다.

$#          모든 argument의 갯수

$?          마지막으로 수행된 명령어가 return한 값

$$          현재 shell script를 수행하고 있는 shell의 process id(pid)

$!          현재shell에서 수행한 마지막 background의 pid

$_          shell command의 마지막 argument를 가르키며,shell start시에는

            shell의 절대 PATH를 가르킨다.


# set aaa bbb ccc ddd eee fff 

- set명령어를 옵션없이 사용하면 positional parameter를 setting한다.

# echo $0      sh   현재shell를 나타낸다.

# echo $1      aaa

# echo $#      5    $# 은 argument의 개수를 나타낸다.

# echo $*      "aaa bbb ccc ddd eee fff"

# echo $@      "aaa" "bbb" "ccc" "ddd" "eee"

- "$*" 와 "$@" 의 차이점은 $*은 Positional parameter의 모든값을 하나의

  문자열(string)으로 취급하며 $@ 는 string을 개개의 문자열로 취급한다.

# echo $$    7637   : shell의 process id


${parameter}           parameter의 값. 이것은 {}뒤에 붙어있는 문자나

                       숫자,_ 와 같은문자와 함께 사용할 때 필요하다.

${#parameter}          parameter값의 문자수. ${#*}나 ${#@}은 positional

                       parameter의 개수를 나타낸다.

${#identifier[*]}             배열 identifier에서 element의 수를 출력한다.

${parameter:-word}     parameter가 set되고 NOT NULL이면 parameter값을 출력하고,

                       그렇지 않으면 word의 값을 출력한다.

${parameter:+word}     parameter가 set되고 NOT NULL이면 word의 값을 출력하고,

                       그렇지 않으면 아무것도 출력하지 않는다.

${parameter:=word}     parameter가 set되고 NOT NULL이면 parameter의 값을

                       출력하고, 그렇지 않으면 word의 값을 출력하고 parameter에

                       word의 값을 assign한다. Positional parameter는

                       이렇게 setting할 수 없다.

${parameter:?word}     parameter가 set되고 NOT NULL이면 parameter값을

                       출력하고, 그렇지 않으면 word를 출력하고 shell를

                       exit한다. word가 생략되면 화면에 표준출력된다.


# dir1=/home/tmp

# echo ${dir1:-/usr/bin}

/home/tmp

# unset X

# echo ${X:-"X is unset"}

X is unset   : X가 unset또는 null이면 word가 출력된다.

# echo ${dir1:+/usr/bin}

/usr/bin     : dir1이 null이면 아무것도 출력되지 않는다.

# echo ${dir1:=/usr/bin}

/home/tmp    : dir1이 unset되었거나 null이라면 /usr/bin이 출력된다.

# echo ${dir1:?/usr/bin}

/home/tmp

# echo ${#dir1}

10               : /users/tmp 의 총 문자갯수

${parameter#pattern}   pattern이 parameter값의 첫문자와 같으면 그문자를

${parameter##pattern}  포함한 부분은 delete된다. ##은 wild card(*)시 사용함.

   

${parameter%pattern}   pattern이 parameter값을 끝문자와 같으면 그문자를

${parameter%%pattern}  포함한 문자는 delete된다. %%은 wild card(*)시 사용함.


# XX=/a/b/c/d/a/b

# echo ${XX#*a}

/b/c/d/a/b

# echo ${XX##*a}

/b

# echo ${XX%a*}

/a/b/c/d/

# echo ${XX%%a*}

/

# AA="12345123"

# echo ${AA#1}

2345123

# echo ${AA##*1}

23

# echo ${AA%3}

1234512

# echo ${AA%%3*}

12

# echo ${AA#5}

12345123

# echo ${AA##*5}

123

# echo ${AA##*3*}


# echo ${AA##6*}

12345123


u        Tilde(~) Substitution


만약 user mary의 home directory가 /users/mary라면

# echo $HOME

/users/mary

# echo ~           : ~ 는 user의 home directory를 나타낸다.

/users/mary

# echo $PWD

/users/mary/tmp

# ls ~+/x*         : ~ 다음의 + 는 현재directory 즉, $PWD의 값을 가르킨다.

/users/mary/tmp/x_file1

/users/mary/tmp/x_file2

# echo $OLDPWD

/users/mary/mail

# ls ~-/f*         : ~ 뒤의 - 는 이전 directory 즉, $OLDPWD의 값을 가르킨다.

/users/mary/mail/from.mike 

/users/mary/mail/from.nick


u        Shell Command Grouping


l         ( command )  : subshell grouping

                 shell은 마치 또다른 script를 call한것처럼 subshell

                 환경에서 command를 수행한다.

l         { command ;} : brace grouping

                    shell은 현재의 shell 환경에서 연속해서command를

수행하며 마지막에 반드시 ;(세미콜론)을 써야한다.


# vi test1.sh

#! /usr/bin/sh

# (command)의 Example


A="aaa"

B="bbb"

C="ccc"

( A="AAA"

B="BBB"

C="CCC"

echo "PID $$ :

      $A $B $C" )

echo "PID $$ :

       $A $B $C"

:wq

# sh test1.sh

PID 28999 : AAA BBB CCC

PID 28999 : aaa bbb ccc

# vi test2.sh

#! /usr/bin/sh

# {command;}의 Example


A="aaa"

B="bbb"

C="ccc"

{ A="AAA"

B="BBB"

C="CCC"

echo "PID $$ :

      $A $B $C" ;}

echo "PID $$ :

       $A $B $C"

:wq

# sh test2.sh

PID 28955 : AAA BBB CCC

PID 28955 : AAA BBB CCC


u        Shell Script의 수행


# sh shell_script

# ksh shell_script

# chmod 777 shell_script

# ./shell_scipt


u        Shell Script Comment


l         shell script에서 comment는 첫라인에 # symbol를 넣는다.

l         shell script에서 첫라인의 #! /usr/bin/sh의 의미는 이 shell은

    Posix shell로 수행한다는 의미이다.


u        Input and Output


stdin(0)         standard input으로서 default는 keyboard이며

                 file descriptor값은 0 이다.

stdout(1)        standard output으로서 default는 terminal display이다.

                 file descriptor값은 1 이다.

stderr(2)        standard error로서 default는 terminal displsy이다.

                 file descriptor값은 2 이다.

<word            표준입력(file descriptor 0)으로 word를 사용한다.

>word            표준출력(file descriptor 1)으로 word를 사용하며,

word라는 file이 생성된다.

>|word           >word와 같으며 noclobber옵션이 설정되있어도 무조건 overwrite한다.

>>word           word라는 file이 존재하면 file에 append한다.

없으면 word라는file을 생성한다.

<>word           word를 입력으로 받아서 다시 word라는 file로 출력한다.

<<word           shell prompt에서 word라는 글자를 만날때까지 command를 입력할 수

                 있으며 word라는 글자를 만나면 shell command가 수행된다.

<&숫자           file descriptor 숫자의 file에서 data를 입력받는다.

>&숫자           file descriptor숫자를 가진 file로 출력한다.

<&-              표준입력을 close하여 keyboard로부터 입력받지 못한다.

>&-              표준출력을 close하여 terminal로 출력하지 않는다.


# ftp -n -i << AAA

>open mars

>user root password

>cd /users

>mget *

>close

AAA

#


# vi datafile       : data file작성

aaa

bbb

ccc

:wq

# vi read.sh

exec 5< datafile  : datafile을 file descriptor 5번으로 open한다.

read -u5 X        : 첫라인을 read하여 X변수에 assign한다.

read -u5 Y         : 둘째라인을 read하여 Y변수에 할당.

read -u5 Z        : 셋째라인을 read하여 Z변수에 할당.

exec 5<&-         : file descriptor 5번 file을 close한다.

echo "$X $Y $Z"   : file descriptor은 3-9까지 쓸수있다.

:wq

# sh read.sh

aaa bbb ccc






u        조건 표현식


test 또는 [ ... ]             Integer,string.file등에 모두사용(old syntax)

(( ... ))              Integer에만 사용(new syntax)

[[ ... ]]              string,file에만 사용(new syntax)


l         String 표현식  # man test 참조

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

[ -b file ]            file이 존재하고 block special file이면 참

[ -c file ]            file이 존재하고 character special file이면 참

[ -d file ]            file이 존재하고 directory이면 참

[ -e file ]            file이 존재하면 참

[ -f file ]            file이 존재하고 ordinary file이면 참

[ -g file ]            file이 존재하고 setgid bit가 set되있으면 참

[ -h file ]            file이 존재하고 symbolic link되었으면 참

[ -k file ]            file이 존재하고 sticky bit가 set되었으면 참

[ -p file ]            file이 존재하고 fifo special file또는 pipe이면 참

[ -r file ]            file이 존재하고 readable하면 참

[ -s file ]            file이 존재하고 file size가 0보다 크면 참

[ -u file ]            file이 존재하고 setuid bit가 set되 있으면 참

[ -w file ]            file이 존재하고 writable하면 참

[ -x file ]            file이 존재하고 executable하면 참

[ -L file ]            file이 존재하고 symbolic link이면 참

[ -O file ]            file이 존재하고 user가 effective user id와 같으면 참

[ -G file ]            file이 존재하고 group이 effective group id와 같으면 참

[ -S file ]            file이 존재하고 socket이면 참

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

[ -n string ]          string의 길이가 non zero면 참

[ -z string ]          string의 길이가 zero이면 참

[ string ]                    string이 not null string이면참





# if [ -f /etc/rc.config ] ; then

# if [ ! -d /usr/bin ] ; then

# if [ -z "$NODENAME" ] ; then

# if [ -x /usr/dt/bin/dtrc ] ; then

# if [[ -n "$NAME" ]] ; then

# if [[ -s /var/spool/lp/pstatus ]] ; then

# if [[ -r /var/run/mrouted.pid ]] ; then

# if [[ -z "$pid" ]] ; then

# if /usr/sbin/envd ; then

# if /sbin/local_is_root ; then

# if [ "$ARRAYMON_PID" ] ; then

# if [ "$START_OV500" ] ; then


[ file1 -nt file2 ]    file1이 존재하고 file2보다 newer이면 참

[ file1 -ot file2 ]    file1이 존재하고 file2보다 older이면 참

[ file1 -ef file2 ]    file1이 존재하고 file2와 equal file이면 참


# if [ /sbin/init.d/spa –nt /sbin/init.d/set_date ] ; then

# if [ /aaa –ot /bbb ] ; then

# if [ /ccc –ef /ddd ] ; then


[ string1 = string2 ]  string1과 string2가 같으면 true

[ string1 = pattern ]  string1과 pattern이 같으면 true

[ string1 != string2 ] string1과 string2가 같지않으면 true

[ string1 != pattern ] string1과 pattern이 같지않으면 true

[ string1 < string2 ]  string1이 string2보다 작으면 true

[ string1 > string2 ]  string1이 string2보다 크면 true


# if [ "$pid" = "" ] ; then

# if [ X$pid != "X" ] ; then

# if [ $HOST != `hostname` ] ; then

# if [ "$MWASTART" > "1" ] ; then

# if [[ $? = 255 ]] ; then


[ exp1 -eq exp2 ]             exp1과 exp2가 같으면 참(equal)

[ exp1 -ne exp2 ]             exp1과 exp2가 같지 않으면 참(not equal)

[ exp1 -lt exp2 ]             exp1이 exp2보다 작으면 참(less than)

[ exp1 -gt exp2 ]             exp1이 exp2보다 크면 참(greater than)

[ exp1 -le exp2 ]             exp1이 exp2보다 작거나 같으면 참(less than or equal)

[ exp1 -ge exp2 ]             exp1이 exp2보다 크거나 같으면 참(greater than or equal)


# if [ $x –ne 0 ] ; then

# if [ $? –eq 0 ] ; then

# if [ "$RWHOD" –eq 1 ] ; then

# if [[ "$rval" –eq ${EXIT_NA} ]] ; then

# while [ ${CNT} –le ${MAX_NISCHECKS} ] ; then

# if [ $# -ge 0 ] ; then

# if [ "$XX" –gt "$YY" ] ; then

# if [ "$X" –lt 1 ] ; then

# if [ $# -ne 1 ] ; then

# if [ `grep $HOSNAME /etc/mail/sendmail.cw|wc –l` -eq 0 ] ; then


( expression )         expression이 참이면 참

! expression           Binary NOT 연산자

exp –a exp2            Binary AND 연산자, 우선순위가 –o 보다 높음.

exp –o exp2            Binary OR 연산자

exp1 && exp2           exp1과 exp2가 모두 참이면 참

exp1 || exp2           exp1가 참이거나 exp2가 참이면 참


# if [ "$GATED" –eq 0 –a "X$pid" = "X" ] ; then

# if [ "$CRON" –eq 1 –a –x /usr/sbin/cron ] ; then

# if [ "$NIS_DOMAIN" –a –f /usr/bin/domainname ] ; then

# if [ "$NIS_MASTER" –ne 0 –o "$NIS_SLAVE" –ne 0 ] ; then

# if [ "$9" = 'S' ] || [ "$9" –lt '2' ] ; then

# if [ "$VTDAEMON_START" –eq 1 ] && [ -x /usr/sbin/vtdaemon ] ; then

# if [[ -r /usr/sbin/swagentd# ]] && [[ -h /usr/sbin/swagentd ]] ; then

# if [ $status !=2 –o –z "$DOMAIN" –o –z "$SERVER" ] ; then

# if (( status == 0 )) && [[ -n $PROTO ]] ; then


l         Integer 표현식


(( integer1 == integer2 ))    integer1과 integer2가 같으면 참

(( integer1 != integer2 ))    integer1과 integer2가 같지 않으면 참

(( integer1 < integer2 ))           integer1이 integer2보다 작으면 참

(( integer1 > integer2 ))           integer1이 integer2보다 크면 참

(( integer1 <= integer2 ))    integer1이 integer2보다 작거나 같으면 참

(( integer1 >= integer2 ))    integer1이 integer2보다 크거나 같으면 참


# if (( $? != 0 )) ; then

# while ((n>0))

# if ((n<2) || !length(part[2])) ; then

# if ( $1 != mypid ) ; then

# if (( $1 > $2 )) ; then


3.Shell Programming


u        if 조건문


if 조건문

then

   명령어

[elif 조건문

then

   명령어]

[else

   명령어]

fi


if 조건문; then 명령어; [elif 조건문; then 명령어;] [else 명령어;] fi


:wq# vi if1.sh

X=hello

if [ $X = hello ]

then

   echo "Welcome"

else

   echo "Goodbye"

fi

:wq

# sh if1.sh

Welcome

# vi if2.sh

if [ -f temp ]

then

   mv temp temp1

elif [ -f temp1 ]

then

   mv temp1 temp2

fi

:wq

# sh if2.sh


u        case 조건문


case 변수 in

변수값1|변수값2…)

   명령어;;

변수값3|변수값4…)

   명령어;;

*)

   명령어;;

esac





#  vi case.sh

case $1 in

-d|-r)

        rmdir $dir1

        echo "directory removed" ;;

-o)

        echo "option -o" ;;

*)     

        echo "Invalid option,Try again..." ;;

esac

:wq

# chmod 777 case1.sh

# ./case.sh -o

option -o


u        while 반복문


while 조건문

do

   명령어

done


- 다음은 모두 같은 while문이다.


while [ 1 ]

do

  echo "Test"

done

while true

do

  echo "Test"

done

while [ : ]

do

  echo "Test"

done

while :

do

  echo "Test"

done


# vi while1.sh

count=$(who|grep -v root|wc -l)

while [ "$count" -gt 0 ]

do

   echo "Users still logged in..."

   sleep 1

   count=$(who|grep -v root|wc -l)

done

:wq

# sh while1.sh


# vi while2.sh

# /usr/bin/sh

#

print -n "Enter a value : "

read Value

print "Thank You"

count=0

while [ "$count" -lt "$Value" ]

do

   (( count=count + 1 ))

   print "Still sleeping for the $count th time..."

   sleep 2

done

print "End of $0"

:wq

# sh while2.sh


u        for 반복문


for 변수 [in 변수값1,변수값2,…]

do

   명령어

done


# vi for1.sh

for name in $(cut -d -f1 /etc/passwd)

do

   mailx $name < message.txt

   echo "Mail sent to $name"

done

:wq

# sh for1.sh

# vi for2.sh

if [[ ! -d "$1" ]]

then

   exit 1

fi

filename=$(ls $1)

for onefile in $filename

do

   if [[ -f ${1}/$onefile ]]

   then

      ll ${1}/$onefile

   elif [[ -d ${1}/$onefile ]]

   then

      ll -d ${1}/$onefile

   fi

done

:wq

# sh for2.sh /etc







u        until 반복문


until 조건문

do

   명령어

done


# vi until.sh

count=$(who|grep -v root|wc -l)

until [ "$count" -eq 0 ]

do

   echo "Users still logged in..."

   sleep 1

   count=$(who|grep -v root|wc -l)

done

:wq

# sh until.sh


u        select 반복문


select 변수 [in 변수값1,변수값2,…]

do

   명령어

done


- select문은 PS3 prompt를 사용한다. PS3 shell 변수의 기본값은 #? 이다.

- 변수는 변수값1,변수값2,… 등이 할당된다.

- 입력된 변수의 값의 숫자는 REPLY라는 shell변수에 저장된다.

- exit,return,break 등의 명령어로 반복문을 빠져나올수 있다.

- [in 변수값1,변수값2,…]가 없을경우에는 Positional Parameter를 사용한다.


# vi edit.sh         ### Edit the file ###

select menu in $(ls) "Exit" ; do

   case $menu in

     Exit) exit;;

     "") echo "Invalid selection. Try again!";;

     *) cp $menu $menu.bak; vi $menu ;;

   esac ; done

:wq





# vi color.sh

  select color in red blue green

  do

     echo "$color is an $color color"

     echo "$REPLY is a REPLY value"

  done

:wq

# sh color.sh

1)red

2)blue

3)green

#? 1

red is an red color

1 is a PEPLY value

#? 2

blue is an blue color

2 is a REPLY value

#? ^C

#


# vi select.sh

PS3="Enter your choice =>"

select menu in "full backup"

                  "partial backup"

do

 case $menu in

 "full backup")

  fbackup –0uf /dev/rmt/0m –i /stand

  echo "Full backup has begun"

  exit 0;;

 "Partial backup")

fbackup –0uf /dev/rmt/0m -i /opt

echo "Partial Backup has begun"

return;;

 *) echo "$REPLY is an invalid

             option. Try again!";;

 esac

done

:wq

# sh select.sh


# vi nest.sh

  #### Nested Select Command Example ###

#! /usr/bin/sh

PS3="Main Choice by number=>"

select menu in "List Files" "Exit"

do

   case $menu in

   "List Files")

      PS3="Sub Choice by number=>"

      select ls_option in "Short" "Long" "Main"

      do

         case $ls_option in

          "Short") lsf;;

           "Long") ll;;

           "Main")

               PS3="Main Choice by number=>"  ## Restore Prompt

               break 1 ;;  ## exit inner loop

           "") echo "$REPLY is an invalid option. Try again!";;

         esac

      done ;;

   "Exit") exit;;

   "") echo "$REPLY is an invalid option. Try again!";;

   esac

done

:wq

# sh nest.sh





u        Function(함수)


function 함수명

{

  shell script

}

함수명()

{

  shell script

}


- shell script안에 선언할수도 있고 밖에 선언할수도 있다.

- 함수명이나 argument로 called될수 있다.

- 같은 process를 반복적으로 사용할때 유리하며 debugging하기가 쉽다.

- typeset -xf name 으로 함수명을 export하여 global 함수로 선언할수 있다.


# vi func1.sh

function exef

{

   if [ -x $1 ]

   then

      echo "$1 is executable"

   fi

}

for file in `ls`

do

   exef $file

done

:wq

# sh func1.sh


# vi func2.sh

Uppercase()

{

   echo $* | tr "[a-z]""[A-Z"]"

}


print -n "Enter in a string:"

read string

upper_string=$(Uppercase $string)

echo "The uppercase string is: $upper_string"

:wq

# sh func2.sh







# vi func3.sh       : Recursive Fuction

bottom_up

{

   typeset SAVEPWD

   echo "\nDirectory being listed is: $PWD\n"

   lsf

   if [ "$PWD" != "/" ]

   then

      SAVEPWD=$PWD

      cd ..

      bottom_up

      cd $SAVEPWD

   else

      echo "That's the end!"

   fi

}

:wq

# sh func3.sh


u        Array(배열)


- shell script에서 사용할수 있는 배열은 1차원배열이다.

- 배열요소(element)는 최대 512-1024까지 쓸수 있다.

- 배열요소는 [0]부터 [1023]까지 쓸수 있다.

- Array subscript인 [N]에서 N은 integer또는 integer expression을 쓸수 있다.


# X[0]=first

# X[1]=second

# X[2]=third

# echo ${X[1]}

second

# echo ${X}         : ${X}는 ${X[0]}과 같음

first

# echo ${X[*]}             : '*'나 '@'는 모든 요소를 가르킴

first second third

# echo ${#X[*]}

3

# i=3

# X[2*(i+1)]=10

# print ${X[8]

10



# set -A YY 100 200 300    : set -A는 변수를 배열로 선언한다.

# print ${YY[0]} ${YY[1]} ${YY[2]}

100 200 300

# set +A YY 150

# print ${YY[@]}

150 200 300




4.Shell Command


u        : 명령어


- ':' 명령어는 아무것도 수행하지 않으며, 어떤 영향도 미치지 않는다. '0'값이 return됨.


# vi xx.sh

if [ -f /opt ]; then

   ls

else

   :            아무것도 수행하지 않는다.

fi

:wq


u        . 명령어


# . /etc/profile


- /etc/profile이라는 프로그램을 수행한다. 이는 sh나 ksh처럼 또하나의 shell을 fork하여

  프로그램을 수행하지 않으며 이 프로그램은 수행가능한 permission이 없어도 된다.

  즉 이 파일은 'x' permission이 없어도 된다.


u        alias 명령어


alias [-x] [ name[=value] … ]


# alias                             : 현재 setting된 모든 alias를 display

# alias a=alias

# a x=lsf

# alias i='

> echo Users logged in are:

> who|sort

> echo I am `whoami`'

# i                                  : alias문을 수행한다.

# unalias i                        : alias변수 i를 unsetting한다.

# unalias -a                       : shell command에서 typing한 모든

                                        alias를 해제한다.

# alias -x who='who|sort'       : Korn shell에서 who를 export하여

                                        subshell에서도 사용가능하다.


u        break 명령어


break [n]


- for,while,until,select문과 같은 반복문에서 exit할 때 사용한다.

- n을 쓰면 n레벨만큼 loop를 exit한다.


# vi break.sh

for file in x y z none

do

   if [ -x $file ]; then

      echo $file

      break

   fi

done

:wq


u        command 명령어


command [arg …]


- argument를 command로서 취급한다.


# command lsf       : lsf를 command로 사용한다.

# command aaa       : aaa를 command로 사용한다.


u        continue 명령어


continue [n]


- for,while,until,select문과 같은 반복문에서 continue이하의 문을 수행하지 않고

다시 시작한다.

    - n을 쓰면 n번째 반복문을 다시 시작한다.


# vi con.sh

for file in x y z

do

   if [ -x $file ]; then

      continue

      echo "$file is executable"

   fi

   echo $file is not executable

done

:wq


u        echo 명령어


echo [arg …]


# echo 'This is a' $var 'example.'

# echo "This is a $var example."

# echo "Enter your user name: \c"

> read user

> echo 'User is' $user


echo 에서 Escape Character

\b     backspace

\c     continue line. new line을

       하지 않고 계속 붙여서 print한다

\f     form feed

\n     new line

\r     carriage return

\t     tab

\v     vertival tab

\\     backslash


u        eval 명령어


eval [arg …]


- argument를 input으로 받아서 명령어로 수행하며 argument는 command나 shell

  script가 될수 있다.


# cmd='ps -ef > ps.out'

# eval $cmd

# eval "grep jones $file|set|echo $1 $2 $3"


u        exec 명령어


exec [arg …]


- 새로운 process나 subshell을 만들어서 argument를 수행하지 않고 현재 shell로

  명령어를 바로 수행한다.

# exec 3< file          file desciptor number 3으로 file을 open한다.

# ecec 2> /dev/null     표준에러를 /dev/null로 출력한다.


u        expr 명령어         # man expr 참조


expr expression {+,-,\*,/} expression

expr expression {=,\>,\>=,\<,\<=,!=} expression

expr string1 : string2


# a=15

# expr $a + 5

20

# count=`expr $count + 5`

# A=batman

# expr substr $A 1 3

bat

# expr index $A m

4


u        fc 명령어


fc [-r] [-e example] [first [last]]

fc –l [-nr] [first [last]]

fc –s [old=new] [first]

fc –e – [old=new] [command]


- fc command는 history file을 list하거나 history file에서 command를 edit할 수있다.


# fc –l            : history file의 내용을 display한다.

# fc –l 20 25

# fc –l 10

# fc –e vi 15 20

# fc –e -          : 방금 실행한 command를 다시 실행한다. # r 명령과 같다.

# fc –e – ls=cd  


u        let 명령어


let "expression"

(( expression ))

- let는 산술 표현을 가능하게 하며 long integer 계산을 한다.


Operator

Description

-

!

/  %

+  -

<  <=  >  >=

==  !=

=

unary minus

logical negation

곱하기,나누기,몫

더하기,빼기

비교

같다,같지 않다

변수 할당


# x=10

# y=2

# let x=x+2

# echo $x

12

# let "x=x/(y+1)"

# echo $x

4

# (( x=x+1 ))

# echo $x

5

# x=12

# let "x<10"

# echo $?

1

# (( x > 10 ))

# echo $?

0

# if (( x > 10 ))

>then echo x greater

>else echo x not greater

>fi

x greater


u        read 명령어


read [-r] name…        : POSIX Shell only

read [-prsu] [name]    : Korn Shell only


-r          라인연속으로 쓰인 라인끝의 \를 해석하지 않는다.

-un         file descriptor n 으로부터 input을 read한다.


# vi read.sh

  while read -r xx yy

  do

     printf "%s %s \n" "$yy" "$xx"

done < input_file

:wq


u        return 명령어


return [n]


- 함수의 실행을 마치고 calling shell script에게 exit status n을 return한다.

- n이 없으면 return status는 함수의 마지막 command의 값이다.

- return이 함수의 밖에서 수행되면 exit로서 실행된다.


# vi return.sh

  search()

  {

     if grep xxx "$1" > /dev/null 2>&1

     then return 1

     else return 2

     fi

  }

:wq

# sh return.sh filename


u      set 명령어


l         Positional Parameter값 setting


# set spring summer fall winter

# echo $3

fall

# echo $*

spring summer fall winter



l         Positional Parameter Sorting


# set third first second

# echo $1 $2 $3

third first second

# set –s               : 값을 lexical order로 sorting함

# echo $1 $2 $3

first second third

# set +s            : unsetting








option         option-name meaning

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

set –a         allexport   모든 parameter가 자동으로 export됨. == set -o allexport

set -C         noclobber   #date>XX시 >로 overwrite하지못하게 함. date>|XX로는 가능

set –e         errexit     shell command fail시 즉시 logout또는 shell을 exit함

set –f         noglob             # ls * 시wild card문자를 인식못함

set –h         trackall   

set –k         keyword    

set –m         monitor     Background jogs이 각각다른 process group에서 수행되고

                           작업이 끝나면 message를 report함

set –o                     set –o monitor와 같이 option-name에 붙여서 옵션을

                           setting함

set –s                     positional parameter를 sort함

set –t                     shell을 exit한후에 command를 수행함

set –u         nounset     substituting시 unset parameter를 error로 취급함

set –v         verbose     command를 display한후 command 수행

set –x         xtrace             command수행시 command와 argument까지 print함.

                           shell script의 debug mode로 사용함.

              

set                        현재 setting된 모든 shell variable을 list함

set -                      -x와 –v option을 turn off하고 flag에 대한 argument

                           검사를 하지 않음

set --                     옵션의 어떤 변화도 하지못하게 함. # set -- -;echo $1

                                      file명으로 시작하는 file을 rm할 경우 # set -- -;rm –aaa


# set –o ignoreeof          : ignoreeof라는 옵션을 turn on

# set +o vi                : vi의 옵션을 turn off

# set –o noglob            : noglob옵션을 turn on 시키고 wild card인

                                    *,[],-,!,? 등을 shell이 해석하지 못하게함

# set –o noexec            : shell의 syntax error를 check하기위해 사용.

                             이 옵션은 interactive shell에서는 사용되지

                                    않으며 shell script에서만 수행됨.

                             noexec 옵션은 실제로 shell을 수행하지 않으면서

                                       shell의 syntax error만을 check하는 명령어다.



# vi set1.sh

  set –o noexec

  echo "This is test

  ls

  cp /aaa /bbb

:wq

# ksh set1.sh

set1.sh: syntax error at line 2 : '"' unmatched

# vi set2.sh

  set –x

  ls

  echo "The Test"

  set +x

  lsf

:wq

# sh set2.sh


u        shift 명령어


shift [n]


shift command는 positional parameter($1,$2,$3..)의 내용을 왼쪽순으로 move한다.


# vi shift1.sh

  yflag=0

  zopt=""

  for arg in "$@"

  do

     if [ "x$arg" = x-y ]

     then

        yflag=1

        shift

     else

       zopt="$2"

       shift 2

     fi

  done

:wq


u        trap 명령어


trap [command] [signal]


- signal 값은 # kill –l또는 # man kill 명령어로 볼수 있음.

# trap "echo 'Command Failed'" 2

                       : ^C(interupt)를 치면 echo 문장이 수행됨.


# trap              : trap 명령을 수행한후 옵션이 없이 trap명령을 수행하면 현재

                    setting된 모든 trap내용을 보여줌

# trap "" 1 2 3

                       : 1}HUP 2)INT 3)QUIT가 입력되도 무시하라.

# trap "echo logout" 0

                       : signal이 '0' 이면 NULL signal로서

                         shell에서 exit할때 command가 수행된다.


u      typeset 명령어


typeset [-][+]옵션  변수명[=변수값]


option      meaning

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

[-]         변수명의 속성을 setting

[+]         변수명의 속성을 turn off

-Ln         왼쪽의 공백을 제거하고 왼쪽에서 n숫자만큼 cut

-Rn         왼쪽에 공백을 채우고 오른쪽에서 n숫자만큼 cut

-Z          오른쪽으로 shift하고, 첫번째 문자가 숫자이고 –L옵션과 같이

            쓰지 않았으면 왼쪽에 숫자0을 채움

-i          변수명을 integer로 선언

-f          변수명이 아니라 함수명으로 변수를 선언

-l          모든 영문대문자를 소문자로 변환

-u          모든 소문자를 대문자로 변환

-r          변수를 read-only로 만듬,즉 변수를 상수로 만듬

-x          변수를 export함, 즉 변수를 전역변수로 만듬

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

# typeset

현재 setting되어있는 변수의 data type을 보여줌

# typeset AA

AA변수를 string변수로 선언,또한 함수내에서 Local변수 즉 지역변수로 선언

하지만, shell에서 변수는 default로 string data type임


# DATA="Today we had very HOT weather"

# typeset –u DATA

# echo $DATA

TODAY WE HAD VERY HOT WEATHER

# typeset +u DATA : DATA변수의 속성을 turn off 

# DATA="as of the "${DATA}

# echo $DATA

as of the TODAY WE HAD VERY HOT WEATHER


# AAA=123456789

# typeset –L3 AAA

# echo $AAA

123


# typeset –LZ X=00005

# print $X

5

# typeset –i X        : 변수X를  integer로 선언 # integer X와 같음

# typeset –i2 X     : 변수X를 2진수로 선언

# typeset –i8 X     : 변수X를 8진수로 선언

# typeset –i10 X    : 변수X를 10진수로 선언

# typeset –i16 X    : 변수X를 16진수로 선언

# typeset -r Y=123  : 변수Y를 readonly변수로 선언 # readonly Y=123과 같음

# typeset -f        : 모든함수와 그 값을 display함

# typeset -xf       : export된 모든함수와 그 값을 display함

# typeset -xf XX    : 함수명 XX를 export하여 global function으로 선언함


u        ulimit 명령어


ulimit  [-f] [n]


- ulimit command는 child process나 subprocess에 의해 사용된는 resources를 제한한다.


# ulimit               : 현재 limit값을 보여준다

# ulimit –f 1000       : 현재process나 향후 process가 write할 수 있는

                          file size를 1000 block(1000*512 byte)으로 제한한다.

# ulimit –f unlimited : child process가 생성할 수 있는 size의 제한을 없앤다.







5.Regular Expression(정규 수식)


u        Pattern Matching과 Regular Expression의 비교 - # man 5 regexp참조


Pattern Matching


Regular Expression

- POSIX shell에서 사용

- file name생성과 case문에서 사용

- UNIX command와 Text Editor에서 사용

  (ed,vi,ex,sed,awk,expr,grep)

- file name을 match한다

- character string을 match한다

- file name을 substitute한다

- string을 search해서 substitute한다

- 사용되는 특수문자

  ?,  *,  [ - ],  !

- 사용되는 특수문자

  .,  [],  -,  ^,  $,  *


u        하나의 문자와 Match - .(dot)


A.          : AB,Ab,AA,A9등과 같이 A다음에오는 어느한문자와 match

...         : 연속된 3문자와 match

# man 5 regexp|col -b|expand > regexp.man

# grep 'RE.' regexp.man       : RE다음에오는 어느한문자와 Match되는 라인만 출력


u        문자의 시작과 Match - ^


^abc        : 첫문자가 abc로 시작되는 문자와 match. abc,abcabc,abcdef등과 match

^C          : 문자의 시작에서 C와 match

^C$         : 하나의 문자 C와 match

^.$         : 하나의 문자로만 구성된 문자와 match

^[ABC]      : 첫문자가 ABC로 시작되는 문자와 match


u        문자의 끝과 Match - $


abc$        : 끝문자가 abc로 끝나는 문자와 match. defgabc,cccabc,abc등과 match

^...$       : 3개의 문자로만 구성된 문자와 match

\.$         : 문자의 끝에서 마침표(.)과 match

\*$         : 문자의 끝에서 (*)와 match



u        문자 Match - []


[Tt]he      : The나 the라는 글자를 search

h[iau]t     : hit,hat,hut의 글자와 match

[ABC]       : A,B,C를 포함하는 문자와 match


u        범위를 포함하는 문자와 Match - [ - ]


[a-z]       : 소문자 a부터 z까지 어느문자와도 match

[0-9]        : 0-9까지 어떤 하나의 숫자와 match

[0-57]      : 0,1,2,3,4,5,7과 match

[a-c5-8X-Z] : a,b,c,5,6,7,8,X,Y,Z중 하나의 문자와 match

[0-3-]      : 0,1,2,3,-와 match


u        Complemented문자 Match - [^  ]


[^ ]        : 공백이 아닌 한문자와 match

[^0-9]      : 0-9까지 숫자가 아닌 하나의 모든문자와 match

[^a-zA-Z]   : 영문 알파벳이 아닌 문자나 숫자와 match

[012^]      : 0,1,2,^와 match

^[^a-z]$    : 소문자을 제외한 나머지 문자중 하나와 match

# man 5 regexp|col -b|expand > regexp.man

# grep '^$' regexp.man|wc -l         : 공백라인수를 출력한다.

# TMOUNT=`/sbin/mount | grep '^/tmp(/| )' | wc -l`

# grep -q -e "^/usr/bin$" -e "^/usr/bin:" -e ":/usr/bin:"\

         -e ":/usr/bin$" /etc/PATH


u        Null 또는 여러 같은문자와 Match - *,+,?


B*          : Null문자,B,BB,BBB...등과 match

AB*C        : AC,ABC,ABBC...등과 match

A+          : A,AA,AAA...등과 match

AB+C        : ABC,ABBC,ABBBC...등과 match

A?          : Null문자 또는 A와 match

AB?C        : AC,ABC와 match

[A-Z]+      : 하나이상의 대문자와 match

(AB)        : AB문자와 match

(AB)+C      : ABC,ABABC,ABABABC...등과 match

AB.*XYZ     : ABXYZ,ABCXYZ,ABCCCCXYZ...등과 match


u        특수문자 Match - \


\*          : 특수문자 *와 match

\$          : 특수문자 $와 match

\\          : 특수문자 \와 match

\\\\\.\*$   : 문자의 끝에서 \\.* 와 match


u        Subexpression - \( ... \)


- \(...\)구문을 사용한다.

- subexpression과 match하는 문자를 recall하기위해 '\숫자'를 사용한다.

- '\숫자' 는 1-9까지 쓸수있다.

- \1 은 1번째 subexpression,\2 는 2번째 subexpression을 나타낸다.


# who

root       console      Oct 23 13:01

root       ttyp1        Oct 27 12:45

root       pts/0        Oct 22 09:03

# who|sed 's/\([^ ][^ ]*\)[^A-Z][^A-Z]*\(.*\)/\2-->\1/'

Oct 23 13:01-->root

Oct 27 12:45-->root

Oct 22 09:03-->root

- 첫번째 /\([^ ][^ ]*\) 는 공백이 아닌 하나이상의 문자와 match하며 뒷부분의

  \1 의 값과 같다.즉, 여기서는 username root를 가르킨다.

- 두번째 \(.*\) 는 최초로 대문자로 시작되는 문자와 match하며 뒷부분의

  \2 의 값과 같다. 여기서는 Oct를 가르킨다.



6.Sed(Stream Editor)


u        sed 형식


sed [-n] command input_file...

sed [-n] [-e command]... [-f script_file]... [input_file...]


-n          화면에 display하지 않는다. 단  p명령어일경우는 화면에 display한다.

            -n옵션은 -e나 -f옵션중 하나와 같이 사용할수 있다.

-e command  command를 editing하며, input file이 없으면 표준입력이 사용된다.

-f script   input file에서 editing command의 script file을 수행한다.


- sed는 입력파일로부터 한라인씩 data를 read한다.

- sed는 default로 화면에 출력을 하며 input file을 modify하지 않는다.


# sed "s/UNIX/Unix/g" file1 > file2.new

# sed -e "s/Miss/Ms/g" -e "s/Mrs/Ms/g" file2

# sed -n "1,10p" file2

# cat script

1,10p

# sed -n -f script file2


u        s(substitute)


[address [,address]] s/string_old/string_new/[flag]


flag        meaning

g           global substitution(전라인을 모두바꾼다)

p           print line

w file      file로 write한다


# sed "s/[Cc]omputer/COMPUTER/g" file1

# sed -e "1,5s/abc/xyz/" -e 's/kbs/mbc/' file1 > file2

# sed "/abcde/s/ab/AB/g" file1

# sed -e 's/abc/xyz/w file2' file1

# sed "3s/the/xyz/g" file1

# sed '3s/^the /xyz/' file1

# sed -e "/the/s/ for /xyz/g

# cat file1| sed "/the/s/ for /xyz/gw file2

# sed "1,8s/aaa/bbb/g" file1 > file2

# sed "/^5/,/^15/s/from/FROM/g"

# sed -e "/^The first time/,/^End of file/s/lsf/ll/g"

# sed "1,$s/\/usr\/bin/\/sbin\/bin/g"


u        d(delete)


# sed "1,10d" fileA

   - fileA에서 1-10라인까지 delete한다.

# sed "/^From/!d" mbox

   - mbox file에서 From으로 시작되는 라인만 제외하고 모두 delete한다.


u        p(print),l(list),=,q(quit),r(read),w(write)


p           standard output에 print한다. -n옵션과 함께써도 print된다.

l           nonprinting문자도 같이 표준출력한다.

=           address 라인의 라인번호를 표준출력한다.

q           현재라인을 출력하고 sed를 종료한다.

r file      file의 내용을 read하여 표준출력한다.

w file      file에 address라인을 write또는 append한다.


# vi cap

   One potato, teo potato,

   three potato, four.

   Five potato, six potato,

   seven potato, more.

:wq


# sed -n "1,2p" cap

One potato, two potato,

three potato, four.


# sed -e "q" cap

One potato, teo potato,

# sed -e "/\./=" -e " /[A-Z]/w file1" cap

One potato, teo potato,

2

three potato, four.

Five potato, six potato,

4

seven potato, more.


# killproc() {

      for x in "$@"

      do

         pid=`ps -e |grep "$x" |sed -e 's/^  *//' -e 's/ .*//'`

         [ ! –z "$pid" ] && echo killing $x && kill $pid &

      done

  }

# findproc() {

    pid=`ps –e |grep "$1" |sed -e 's/^  *//' -e 's/ .*//'`

    echo $pid

  }

# killproc() {           

      echo stopping $1

      pid=`/usr/bin/ps -e |

            /usr/bin/grep "$1" |

            /usr/bin/sed -e 's/^  *//' -e 's/ .*//'`

            [ "$pid" != "" ] && kill $pid

  }

# if [ "$RWHOD" –ne 1 ]; then

      rval=2

  else

      pid=`ps -el | awk '( ($NF ~ /rwhod/) && ($4 != mypid) &&

           ($5 != mypid)) { print $4 }' mypid=$$ `

      if [ "X$pid" != "X" ]; then

         if kill $pid; then

            echo "rwhod stopped"

         else

            rval=1

            echo "Unable to stop rwhod"

         fi

      fi

  fi

#

#

#

# ARRAYMON_PID=`ps -ef | awk '$0 ~ /.*arraymon*/ && $0 !~ /.*awk.*/

                  { print $2 }'`

  if [ "$ARRAYMON_PID" ]

  then

     echo "Killing disk array monitor daemon."

     kill -9 $ARRAYMON_PID

     sleep 2

     ARRAYMON_PID=`ps -ef | awk '$0 ~ /.*arraymon*/ && $0 !~ /.*awk.*/

                     { print $2 }'`

     if [ "$ARRAYMON_PID" ]

     then

       echo "ERROR:  Could not kill ${ARRAY_MONITOR_DAEMON}"

     fi

  fi

#




























7.Shell Program 예제


-shell script를 위한 data file은 다음과 같다.

# vi data

  100 200 300 400

  500 600 700 800

  900 1000 1100 1200

  1300 1400 1500 1600

  1200 800 400 0

:wq

# vi exp1.sh

if [[ ! -f "$1" ]]

then

   echo "${0##*/}"

   exit 1

else

   filename=$1

fi

exec 3< $filename : file descriptor 3으로 filename를 open

typeset -i II=0   : XX를 integer로 선언

while read -u3 AA[0] AA[[1] AA[2] AA[3]

do

   for II in 0 1 2 3

   do

      (( total[II]=${total[II]} + ${AA[II]} ))

   done

print "Subtotal : "

print ${total[*]}

done

print "Total for the four columns are : "

print ${total[@]}

:wq

# sh exp1.sh












#!/usr/bin/sh

######################## /etc/profile ##########################  


trap "" 1 2 3                   

PATH=/usr/bin:/usr/ccs/bin:/usr/contrib/bin

MANPATH=/usr/share/man:/usr/contrib/man:/usr/local/man

if [ ! -d /usr/sbin ]

then

   PATH=$PATH:/sbin

else

   if [ -r /etc/PATH ]

   then

      grep -q -e "^/usr/bin$" -e "^/usr/bin:" -e ":/usr/bin:"\

                -e ":/usr/bin$" /etc/PATH

      if [ $? -eq 0 ]

      then

         PATH=`cat /etc/PATH`

      else

         PATH=$PATH:`cat /etc/PATH`

      fi

   fi

fi

export PATH

if [ -r /etc/MANPATH ]

then

   MANPATH=`cat /etc/MANPATH`

fi

export MANPATH

if [ -r /etc/TIMEZONE ]

then

   . /etc/TIMEZONE 

else

   TZ=MST7MDT       

   export TZ

fi

if [ ! "$VUE" ]; then

   if [ "$TERM" = "" -o "$TERM" = "unknown" -o "$TERM" = "dialup"  \

                         -o "$TERM" = "network" ]

   then

      eval `ttytype -s -a`

   fi

   export TERM

   if [ "$ERASE" = "" ]

   then

      ERASE="^H"

      export ERASE

   fi

   stty erase $ERASE

   trap "echo logout" 0

   cat /etc/copyright

   if [ -r /etc/motd ]

   then

      cat /etc/motd

   fi

   if [ -f /usr/bin/mail ]

   then

      if mail –e

      then echo "You have mail."

      fi

   fi

   if [ -f /usr/bin/news ]

   then news –n

   fi

   if [ -r /tmp/changetape ]

   then

      echo "\007\nYou are the first to log in since backup:"

      echo "Please change the backup tape.\n"

      rm -f /tmp/changetape

   fi

fi

trap 1 2 3

###################### The End ##########################


#!/usr/bin/sh

############# /.profile ################  


set +u

PATH=/usr/sbin:$PATH:/sbin:/home/root

if [ ! "$VUE" ]; then

   if [ "$TERM" = "" ]

   then

      eval ` tset -s -Q -m ':?hp' `

   else

      eval ` tset -s -Q `

   fi

   stty erase "^H" kill "^U" intr "^C" eof "^D" susp "^Z"

   stty hupcl ixon ixoff

   tabs

   echo

   echo "Value of TERM has been set to \"$TERM\". "

   export TERM

   EDITOR=vi

   export EDITOR

fi

set –u

trap "echo 'logout root'" 0

MAIL=/var/mail/root

echo "WARNING:  YOU ARE SUPERUSER !!\n"

export PS1=`hostname`':$PWD# '

############################# The End ##############################





#!/sbin/sh

######################## /sbin/init.d/inetd #######################

PATH=/sbin:/usr/sbin:/usr/bin

export PATH

rval=0

set_return() {

        x=$?

        if [ $x -ne 0 ]; then

                echo "EXIT CODE: $x"

                rval=1  # always 1 so that 2 can be used for other reasons

        fi

}

case "$1" in

start_msg)

   echo "Start Internet services  daemon" ;;

stop_msg)

   echo "Stopping Internet services daemon" ;;

'start')

   if [ -f /etc/rc.config ]; then

      . /etc/rc.config

   else

      echo "ERROR: /etc/rc.config defaults file MISSING"

   fi

   mask=`umask`

   umask 000

   [ -x /usr/sbin/inetd ] && /usr/sbin/inetd $INETD_ARGS

   if [ $? -eq 0 ]; then

      echo "Internet Services started"

   else

      echo "Unable to start Internet Services"

   fi

   umask $mask

   ;;

'stop')

   if [ -f /etc/rc.config ]; then

      . /etc/rc.config

   else

      echo "ERROR: /etc/rc.config defaults file MISSING"

   fi

   /usr/sbin/inetd -k

   set_return

   if [ $rval -eq 0 ]; then

      echo "Internet Services stopped"

   else

      echo "Unable to stop Internet Services"

   fi

   ;;

*)

   echo "usage: $0 {start|stop}"

   rval=1

   ;;

esac

exit $rval

############################ The End ##############################3

#!/sbin/sh

############# /sbin/rc ################      


arg=$1

arg2=$2

PATH=/sbin

export PATH

/sbin/stty clocal icanon echo opost onlcr ixon icrnl ignpar 2> /dev/null

umask 022

get_scripts() {

   state=$1

   mode=$2

   dir=/sbin/rc${state}.d

   ls $dir 2>/dev/null |

   while read name

   do

      case $name in

      ${mode}*)

         path=$dir/$name

         if [ "$mode" = "S" ]; then

            desc=`$path start_msg`

         elif [ "$mode" = "K" ]; then

            desc=`$path stop_msg`

         fi

         echo $path $desc

     esac

  done

}

if [ -f /sbin/rc.utils ]; then

   . /sbin/rc.utils

else

   init_list()

   {

      echo $1

   }

   add_list()

   {

      eval $1

   }

   run_list()

   {

      :

   }

fi

# If /etc/rc.config contains default information (first boot),

# /sbin/auto_parms will invoke /sbin/set_parms to remedy the situation.

# For 10.0 release, the default HOSTNAME is unset or an empty string.

# Assume a timezone if /etc/TIMEZONE does not exist.

TZ=EST5EDT

if [ -f /etc/rc.config ]; then

   . /etc/rc.config

   if [ -x /sbin/auto_parms ]; then

      /sbin/auto_parms

   else

      echo "\nWARNING: /sbin/auto_parms does not exist"

      echo "DHCP invocation skipped."

   fi

else

   echo "\nWARNING: /etc/rc.config does not exist"

   echo "System name not set, default $TZ assumed."

fi

export TZ

# Set runlevel information

set `who -r` x

new=$7         # new run level

old=$9         # previous run level

# Check to see if we are run from /etc/inittab, or from the command line.

# If run from the command line, set the old run-level to the new run-level.

if [ $PPID != 1 ]; then

   old=$new

   # If the new run-level was specified on the command line,go to that state

   # instead.

   if [[ -n $arg2 ]]; then

      new=$arg2

   fi

fi

if [ "$new" = S ]; then

   new=0

   tosingle=1

else

   tosingle=0

fi

BOOT=0

if [ "$old" = S ]; then

   old=0

   BOOT=1

fi

# Process scripts

found=0

if [ "$new" -gt "$old" ]; then

   # new run level is higher than old, so run start scripts in

   # all intermediate run levels and in new run level.

   if [ $BOOT = 1 ]; then

      init_list "HP-UX Start-up in progress"

   else

      init_list "Transition to run-level $new in progress"

   fi

   typeset -i lvl=$old

   lvl=lvl+1

   while [ $lvl -le "$new" ]; do

      get_scripts $lvl S |

      while read name descrip; do

         if [ -s "$name" ]; then

            add_list "$name start" "$descrip"

            found=1

         fi

      done

      lvl=lvl+1

   done

elif [ "$new" -lt "$old" ]; then

   # new run level is lower than old level, so run kill scripts

   # in all intermediate levels and in new level.

   if [ "$new" = 0 ]; then

      init_list "System shutdown in progress"

   else

      init_list "Transition to run-level $new in progress"

   fi

   typeset -i lvl=$old

   lvl=lvl-1

   while [ $lvl -ge "$new" ]; do

      get_scripts $lvl K |

      while read name descrip; do

         if [ -s "$name" ]; then

            add_list "$name stop" "$descrip"

            found=1

         fi

      done

      lvl=lvl-1

   done

   # If we're ending up in state 0 or S, run the start scripts for

   # that state.

   if [ "$new" = 0 ]; then

      get_scripts 0 S |

      while read name descrip; do

         if [ -s "$name" ]; then

            add_list "$name start" "$descrip"

            found=1

         fi

      done

   fi

else

   # old and new run levels are the same.  Assume that execution

   # is from the command line and run start scripts for the current

   # run level

   init_list "Starting subsystems for run-level $new"

   get_scripts ${new} S |

   while read name descrip; do

      if [ -s "$name" ]; then

         add_list "$name start" "$descrip"

         found=1

      fi

   done

fi

if [ $found = 1 ]; then

   if [ "$BOOT" = 1 ]; then

      run_list boot

   else

      run_list

   fi

fi

if [ "$new" = 0 ]; then

   case $arg in

   "shutdown")

      exec /sbin/sh

      ;;

   "reboot")

      /sbin/reboot

      ;;

   "off")

      /sbin/reboot -h

      ;;

   esac

   #If transitioned to real state 0 (that is, not state S) via init, halt.

   if [[ $PPID -eq 1 && "$tosingle" -ne 1 ]]; then

      /sbin/reboot -h

   fi

fi

# Output message to indicate completion

echo

if [ $BOOT = 1 ]; then

   echo "The system is ready."

else

   echo "Transition to run-level $new is complete."

fi

############################## The End #################################3




















#!/sbin/sh

##################### /sbin/init.d/net ##########################

#

# net:  configure lan interface(s) at initialization time.

# /etc/rc.config.d/netconf defines the configuration parameters:

#

# INTERFACE_NAME[i]:      network interface name (e.g., lan0)

# IP_ADDRESS[i]:          IP address of your system in decimal dot format

# SUBNET_NETMASK[i]:     subnetwork mask in decimal dot format

# BROADCAST_ADDRESS[i]:  broadcast address (other than default) in decimal

#                             format

# LANCONFIG_ARGS[i]:      lanconfig(1m) options (e.g., ieee, ether)

# LOOPBACK_ADDRESS:       loopback address (always 127.0.0.1)

#

# ROUTE_DESTINATION[i]:  route destination

# ROUTE_MASK[i]:       subnet mask

# ROUTE_GATEWAY[i]:       local or remote IP address of gateway

# ROUTE_COUNT[i]:         zero for local gateway, one for remote gateway

# ROUTE_ARGS[i]:          route command options and arguments

#

###########################################################################


set +u  

export PATH=/sbin:/usr/sbin:$PATH

NETCONF=/etc/rc.config.d/netconf

NETSTAT_DATA=/var/adm/netstat_data

OKAY=0

ERROR=1

WARNING=2

# $1 = name of array

# return highest array element index in env; return -1 if no elements

function maxindex {

   # find only lines that start with "var[...]=", grab only the number

   # between "[...]", and print only the last one.

   # we would like to use `sed` as follows:

   #    typeset i=$(set | sed -n 's/^'$1'\[\([[:digit:]]\{1,\}\)\]=.*$/\1/p'

   #                | tail -1)

   # but it is not guaranteed to be in a mounted file system at this time.

   typeset line

   typeset i=-1

   set | while read line; do

      # strip "var[" and "]=...", leaving only number between "[...]"

      line=${line#*$1\[}

      line=${line%%\]=*}

      # if line is all digits, we found "var[...]=...",

      # and line is string between "[...]"

      if [[ -n $line && -z ${line##*([[:digit:]])} ]]; then

         i=$line

      fi

   done

   print -- $i

   return 0

}

##########

#  main   #

##########

case $1 in

start_msg)

   print "Configure LAN interfaces"

   exit $OKAY

   ;;

stop_msg)

   print "Unconfigure LAN interfaces"

   exit $OKAY

   ;;

stop)

   exit $OKAY

   ;;

start)

   ;;  # fall through

*)

   print "USAGE: $0 {start_msg | stop_msg | start | stop}" >&2

   exit $ERROR

   ;;

esac

###########

#  start  #

###########

# Remove the existing /var/adm/netstat_data file.  The first time

# netstat is executed, a new /var/adm/netstat_data file will be

# created.

rm -f $NETSTAT_DATA

# Get actual configuration

if [[ -f $NETCONF ]]; then

   . $NETCONF               # display any errors

   if (($? != 0)); then

      # NB: this is not working as expected:  status is not propagated!

      print "ERROR:   Incorrect data in the file $NETCONF." >&2

      exit $ERROR

   fi

else

   print "ERROR:   Missing the file $NETCONF." >&2

   exit $ERROR

fi

rval=$OKAY

# Do ifconfig and lanconfig commands for each interface

# `foo=$(print $foo)` collapses whitespace, remove surrounding whitespace

# We can have __fewer__ IP_ADDRESSes than INTERFACE_NAMEs (interfaces to be

# ignore).  We can also have __fewer__ SUBNET_MASKs, BROADCAST_ADDRESSes and

# LANCONFIG_ARGS (defaulted).  But we cannot have __more__.

# sanity check

nIF=$(maxindex INTERFACE_NAME)

if (($(maxindex IP_ADDRESS) > nIF)) || \

   (($(maxindex SUBNET_MASK) > nIF)) || \

   (($(maxindex BROADCAST_ADDRESS) > nIF)) || \

   (($(maxindex LANCONFIG_ARGS) > nIF))

then

   print "WARNING: Missing INTERFACE_NAME for corresponding IP_ADDRESS, SUBNET_MASK," >&2

   print "         BROADCAST_ADDRESS or LANCONFIG_ARGS in the file" >&2

   print "         $NETCONF.  Excess variables will be ignored." >&2

   rval=$WARNING

fi

i=0

while ((i <= nIF)); do

   NAME=$(print ${INTERFACE_NAME[i]})

   INTERFACE_NAME[i]=$NAME          # without whitespace for route tests below

   IP=$(print ${IP_ADDRESS[i]})

   IP_ADDRESS[i]=$IP                 # without whitespace for route tests below

   if [[ $IP = "RARP" ]]; then

      IP=`/usr/sbin/rarpc $NAME`

      IP_ADDRESS[i]=$IP              # without whitespace for route tests below

   fi

   if [[ -n $NAME && -n $IP ]]; then

      MASK=$(print ${SUBNET_MASK[i]})

      [[ -n "$MASK" ]] && MASK="netmask $MASK"

      BCAST=$(print ${BROADCAST_ADDRESS[i]})

      [[ -n "$BCAST" ]] && BCAST="broadcast $BCAST"

      PROTO=$(print ${LANCONFIG_ARGS[i]})    # do not set PROTO to any default

      emsg=$(ifconfig $NAME $IP $MASK $BCAST up 2>&1)

      status=$?

      if ((status == 0)) && [[ -n $PROTO ]] ; then

         emsg=$(lanconfig $NAME $PROTO 2>&1)

         status=$?

      fi

      if ((status != 0)); then

         print "ERROR:   $NAME interface: $emsg" >&2

         rval=$ERROR

      fi

   fi

   let i=i+1

done

IP=$(print $LOOPBACK_ADDRESS)

if [[ -n $IP ]]; then

   emsg=$(ifconfig lo0 $IP up 2>&1)

   if (($? != 0)); then

      print "ERROR:   lo0 interface: $emsg" >&2

      rval=$ERROR

   fi

else

   print "ERROR:   Missing LOOPBACK_ADDRESS in the file $NETCONF." >&2

   print "         lo0 interface not initialized." >&2

   rval=$ERROR

fi

# Do route command for each configured route

# Note:  ${IP_ADDRESS[i]} must have whitespace removed already (above)

# We must have the __same__ number of ROUTE_GATEWAYs as ROUTE_DESTINATIONs.

# But we can have __fewer__ ROUTE_COUNTs and ROUTE_MASKs (defaulted).

n=$(maxindex ROUTE_DESTINATION)

if (($(maxindex ROUTE_GATEWAY) != n)) || \

   (($(maxindex ROUTE_COUNT) > n))

then

   print \

      "WARNING: Missing ROUTE_DESTINATION for corresponding ROUTE_GATEWAY" >&2

   print "         or ROUTE_COUNT in the file $NETCONF." >&2

   print "         Excess variables will be ignored." >&2

   rval=$WARNING

fi

i=0

while ((i <= n))

do

   DEST=$(print ${ROUTE_DESTINATION[i]})

   GWAY=$(print ${ROUTE_GATEWAY[i]})

   if [[ -n $DEST && -n $GWAY ]]; then

      COUNT=$(print ${ROUTE_COUNT[i]})

      if [[ -z $COUNT ]]; then

         # default COUNT:  if GWAY is one of the local interface IP

         # addresses, count is 0; otherwise, count is 1.

         COUNT=1

         k=0

         while ((k <= nIF)); do

            if [[ $GWAY = ${IP_ADDRESS[k]} && -n ${INTERFACE_NAME[k]} ]]; then

               COUNT=0

               break;

            fi

            let k=k+1

         done

      fi

      ARGS=${ROUTE_ARGS[i]}

      MASK=$(print ${ROUTE_MASK[i]})

      if [[ -z $MASK ]]; then

          # No subnet mask

          if [[ -z $ARGS ]]; then

             # No arguments

             emsg=$(route add $DEST $GWAY $COUNT 2>&1)

          else

             # With arguments

             emsg=$(route $ARGS add $DEST $GWAY $COUNT 2>&1)

          fi

      else

         # Subnet mask has been entered.

         if [[ -z $ARGS ]]; then

            # No arguments

            emsg=$(route add $DEST netmask $MASK $GWAY $COUNT 2>&1)

         else

            # With arguments

            emsg=$(route $ARGS add $DEST netmask $MASK $GWAY $COUNT 2>&1)

         fi

      fi

      # ignore "entry in use" errors.  these can arise because we

      # booted via NFS diskless, which added routes already

      if (($? != 0)) && [[ -n ${emsg##*entry in use*} ]]; then

         print "ERROR:   $emsg" >&2

         rval=$ERROR

      fi

   fi

   let i=i+1

done

# add loopback route for local interfaces to improve performance

k=0

while ((k <= nIF))

do

   if [[ -n ${IP_ADDRESS[k]} && -n ${INTERFACE_NAME[k]} ]]; then

      emsg=$(route add ${IP_ADDRESS[k]} $LOOPBACK_ADDRESS 0 2>&1)

      if (($? != 0)) && [[ -n ${emsg##*entry in use*} ]]; then

         print "ERROR:   $emsg" >&2

         rval=$ERROR

      fi

   fi

   let k=k+1

done

exit $rval

##################### The End  ###########################





 소개


u      Shell 종류


/usr/bin/sh      POSIX Shell

/usr/bin/ksh     Korn Shell

/usr/old/bin/sh  Bourne Shell

/usr/bin/csh     C Shell

/usr/bin/keysh   Key Shell

/usr/bin/rksh    Restricted Korn Shell

/usr/bin/rsh     Restricted Shell


u      Shell Startup 파일


Korn Shell     /etc/profile -> $HOME/.profile -> $HOME/.kshrc

Bourne Shell   /etc/profile -> $HOME/.profile

POSIX Shell    /etc/profile -> $HOME/.profile -> $HOME/.kshrc

C Shell        $HOME/.login -> $HOME/.cshrc


2.Shell Parameter


u      Parameter Substitution


l         Parameter Setting


# Parameter=Value

# 변수명=값  : Named Parameter


l         Parameter의 Unsetting


# unset parameter

  # unset 변수명

u        Command Substitution


# $(command)       # `command`


# XX="12345"

# echo $XX

12345

# HOST=‘hostname‘

# echo $HOST     : # HOST=`hostname` 문장은 # HOST=$(hostname)과 같다

ssosvr3           : 즉, `command` 문장과 $(command)는 같은 뜻이다

# PS1=‘hostname‘':$PWD# '

# PS1=$(hostname)':$PWD# '; echo $PS1

ssosvr3:/#

# W1="A"; W2="B"; W3="C"

# WORD=${W1}AA${W2}BB${W3}CC

# echo $WORD

AAABBBCCC

# unset WORD

- $10과 ${10}은 다르다. 왜냐하면 $10은 positional parameter $1값에

   0값이 붙여서 출력되며, ${10}은 positional parameter 10번째의 값을

   나타내기 때문이다.


u        Positional Parameter(위치변수)


shell-script  arg1  arg2  arg3  arg4

$0               $1    $2     $3    $4

Positional Parameter : $1,$2,$3,$4

$0          shell script명을 나타낸다

$1          첫번째 argument를 나타낸다. 즉, arg1

$2          두번째 argument를 나타낸다. 즉, arg2

$*          "arg1 arg2 arg3 arg4 ..." 즉,모든 argument와 같다.

$@          "arg1" "arg2" "arg3" "arg4..." 즉,개개의 argument와 같다.

$#          모든 argument의 갯수

$?          마지막으로 수행된 명령어가 return한 값

$$          현재 shell script를 수행하고 있는 shell의 process id(pid)

$!          현재shell에서 수행한 마지막 background의 pid

$_          shell command의 마지막 argument를 가르키며,shell start시에는

            shell의 절대 PATH를 가르킨다.


# set aaa bbb ccc ddd eee fff 

- set명령어를 옵션없이 사용하면 positional parameter를 setting한다.

# echo $0      sh   현재shell를 나타낸다.

# echo $1      aaa

# echo $#      5    $# 은 argument의 개수를 나타낸다.

# echo $*      "aaa bbb ccc ddd eee fff"

# echo $@      "aaa" "bbb" "ccc" "ddd" "eee"

- "$*" 와 "$@" 의 차이점은 $*은 Positional parameter의 모든값을 하나의

  문자열(string)으로 취급하며 $@ 는 string을 개개의 문자열로 취급한다.

# echo $$    7637   : shell의 process id


${parameter}           parameter의 값. 이것은 {}뒤에 붙어있는 문자나

                       숫자,_ 와 같은문자와 함께 사용할 때 필요하다.

${#parameter}          parameter값의 문자수. ${#*}나 ${#@}은 positional

                       parameter의 개수를 나타낸다.

${#identifier[*]}             배열 identifier에서 element의 수를 출력한다.

${parameter:-word}     parameter가 set되고 NOT NULL이면 parameter값을 출력하고,

                       그렇지 않으면 word의 값을 출력한다.

${parameter:+word}     parameter가 set되고 NOT NULL이면 word의 값을 출력하고,

                       그렇지 않으면 아무것도 출력하지 않는다.

${parameter:=word}     parameter가 set되고 NOT NULL이면 parameter의 값을

                       출력하고, 그렇지 않으면 word의 값을 출력하고 parameter에

                       word의 값을 assign한다. Positional parameter는

                       이렇게 setting할 수 없다.

${parameter:?word}     parameter가 set되고 NOT NULL이면 parameter값을

                       출력하고, 그렇지 않으면 word를 출력하고 shell를

                       exit한다. word가 생략되면 화면에 표준출력된다.


# dir1=/home/tmp

# echo ${dir1:-/usr/bin}

/home/tmp

# unset X

# echo ${X:-"X is unset"}

X is unset   : X가 unset또는 null이면 word가 출력된다.

# echo ${dir1:+/usr/bin}

/usr/bin     : dir1이 null이면 아무것도 출력되지 않는다.

# echo ${dir1:=/usr/bin}

/home/tmp    : dir1이 unset되었거나 null이라면 /usr/bin이 출력된다.

# echo ${dir1:?/usr/bin}

/home/tmp

# echo ${#dir1}

10               : /users/tmp 의 총 문자갯수

${parameter#pattern}   pattern이 parameter값의 첫문자와 같으면 그문자를

${parameter##pattern}  포함한 부분은 delete된다. ##은 wild card(*)시 사용함.

   

${parameter%pattern}   pattern이 parameter값을 끝문자와 같으면 그문자를

${parameter%%pattern}  포함한 문자는 delete된다. %%은 wild card(*)시 사용함.


# XX=/a/b/c/d/a/b

# echo ${XX#*a}

/b/c/d/a/b

# echo ${XX##*a}

/b

# echo ${XX%a*}

/a/b/c/d/

# echo ${XX%%a*}

/

# AA="12345123"

# echo ${AA#1}

2345123

# echo ${AA##*1}

23

# echo ${AA%3}

1234512

# echo ${AA%%3*}

12

# echo ${AA#5}

12345123

# echo ${AA##*5}

123

# echo ${AA##*3*}


# echo ${AA##6*}

12345123


u        Tilde(~) Substitution


만약 user mary의 home directory가 /users/mary라면

# echo $HOME

/users/mary

# echo ~           : ~ 는 user의 home directory를 나타낸다.

/users/mary

# echo $PWD

/users/mary/tmp

# ls ~+/x*         : ~ 다음의 + 는 현재directory 즉, $PWD의 값을 가르킨다.

/users/mary/tmp/x_file1

/users/mary/tmp/x_file2

# echo $OLDPWD

/users/mary/mail

# ls ~-/f*         : ~ 뒤의 - 는 이전 directory 즉, $OLDPWD의 값을 가르킨다.

/users/mary/mail/from.mike 

/users/mary/mail/from.nick


u        Shell Command Grouping


l         ( command )  : subshell grouping

                 shell은 마치 또다른 script를 call한것처럼 subshell

                 환경에서 command를 수행한다.

l         { command ;} : brace grouping

                    shell은 현재의 shell 환경에서 연속해서command를

수행하며 마지막에 반드시 ;(세미콜론)을 써야한다.


# vi test1.sh

#! /usr/bin/sh

# (command)의 Example


A="aaa"

B="bbb"

C="ccc"

( A="AAA"

B="BBB"

C="CCC"

echo "PID $$ :

      $A $B $C" )

echo "PID $$ :

       $A $B $C"

:wq

# sh test1.sh

PID 28999 : AAA BBB CCC

PID 28999 : aaa bbb ccc

# vi test2.sh

#! /usr/bin/sh

# {command;}의 Example


A="aaa"

B="bbb"

C="ccc"

{ A="AAA"

B="BBB"

C="CCC"

echo "PID $$ :

      $A $B $C" ;}

echo "PID $$ :

       $A $B $C"

:wq

# sh test2.sh

PID 28955 : AAA BBB CCC

PID 28955 : AAA BBB CCC


u        Shell Script의 수행


# sh shell_script

# ksh shell_script

# chmod 777 shell_script

# ./shell_scipt


u        Shell Script Comment


l         shell script에서 comment는 첫라인에 # symbol를 넣는다.

l         shell script에서 첫라인의 #! /usr/bin/sh의 의미는 이 shell은

    Posix shell로 수행한다는 의미이다.


u        Input and Output


stdin(0)         standard input으로서 default는 keyboard이며

                 file descriptor값은 0 이다.

stdout(1)        standard output으로서 default는 terminal display이다.

                 file descriptor값은 1 이다.

stderr(2)        standard error로서 default는 terminal displsy이다.

                 file descriptor값은 2 이다.

<word            표준입력(file descriptor 0)으로 word를 사용한다.

>word            표준출력(file descriptor 1)으로 word를 사용하며,

word라는 file이 생성된다.

>|word           >word와 같으며 noclobber옵션이 설정되있어도 무조건 overwrite한다.

>>word           word라는 file이 존재하면 file에 append한다.

없으면 word라는file을 생성한다.

<>word           word를 입력으로 받아서 다시 word라는 file로 출력한다.

<<word           shell prompt에서 word라는 글자를 만날때까지 command를 입력할 수

                 있으며 word라는 글자를 만나면 shell command가 수행된다.

<&숫자           file descriptor 숫자의 file에서 data를 입력받는다.

>&숫자           file descriptor숫자를 가진 file로 출력한다.

<&-              표준입력을 close하여 keyboard로부터 입력받지 못한다.

>&-              표준출력을 close하여 terminal로 출력하지 않는다.


# ftp -n -i << AAA

>open mars

>user root password

>cd /users

>mget *

>close

AAA

#


# vi datafile       : data file작성

aaa

bbb

ccc

:wq

# vi read.sh

exec 5< datafile  : datafile을 file descriptor 5번으로 open한다.

read -u5 X        : 첫라인을 read하여 X변수에 assign한다.

read -u5 Y         : 둘째라인을 read하여 Y변수에 할당.

read -u5 Z        : 셋째라인을 read하여 Z변수에 할당.

exec 5<&-         : file descriptor 5번 file을 close한다.

echo "$X $Y $Z"   : file descriptor은 3-9까지 쓸수있다.

:wq

# sh read.sh

aaa bbb ccc






u        조건 표현식


test 또는 [ ... ]             Integer,string.file등에 모두사용(old syntax)

(( ... ))              Integer에만 사용(new syntax)

[[ ... ]]              string,file에만 사용(new syntax)


l         String 표현식  # man test 참조

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

[ -b file ]            file이 존재하고 block special file이면 참

[ -c file ]            file이 존재하고 character special file이면 참

[ -d file ]            file이 존재하고 directory이면 참

[ -e file ]            file이 존재하면 참

[ -f file ]            file이 존재하고 ordinary file이면 참

[ -g file ]            file이 존재하고 setgid bit가 set되있으면 참

[ -h file ]            file이 존재하고 symbolic link되었으면 참

[ -k file ]            file이 존재하고 sticky bit가 set되었으면 참

[ -p file ]            file이 존재하고 fifo special file또는 pipe이면 참

[ -r file ]            file이 존재하고 readable하면 참

[ -s file ]            file이 존재하고 file size가 0보다 크면 참

[ -u file ]            file이 존재하고 setuid bit가 set되 있으면 참

[ -w file ]            file이 존재하고 writable하면 참

[ -x file ]            file이 존재하고 executable하면 참

[ -L file ]            file이 존재하고 symbolic link이면 참

[ -O file ]            file이 존재하고 user가 effective user id와 같으면 참

[ -G file ]            file이 존재하고 group이 effective group id와 같으면 참

[ -S file ]            file이 존재하고 socket이면 참

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

[ -n string ]          string의 길이가 non zero면 참

[ -z string ]          string의 길이가 zero이면 참

[ string ]                    string이 not null string이면참





# if [ -f /etc/rc.config ] ; then

# if [ ! -d /usr/bin ] ; then

# if [ -z "$NODENAME" ] ; then

# if [ -x /usr/dt/bin/dtrc ] ; then

# if [[ -n "$NAME" ]] ; then

# if [[ -s /var/spool/lp/pstatus ]] ; then

# if [[ -r /var/run/mrouted.pid ]] ; then

# if [[ -z "$pid" ]] ; then

# if /usr/sbin/envd ; then

# if /sbin/local_is_root ; then

# if [ "$ARRAYMON_PID" ] ; then

# if [ "$START_OV500" ] ; then


[ file1 -nt file2 ]    file1이 존재하고 file2보다 newer이면 참

[ file1 -ot file2 ]    file1이 존재하고 file2보다 older이면 참

[ file1 -ef file2 ]    file1이 존재하고 file2와 equal file이면 참


# if [ /sbin/init.d/spa –nt /sbin/init.d/set_date ] ; then

# if [ /aaa –ot /bbb ] ; then

# if [ /ccc –ef /ddd ] ; then


[ string1 = string2 ]  string1과 string2가 같으면 true

[ string1 = pattern ]  string1과 pattern이 같으면 true

[ string1 != string2 ] string1과 string2가 같지않으면 true

[ string1 != pattern ] string1과 pattern이 같지않으면 true

[ string1 < string2 ]  string1이 string2보다 작으면 true

[ string1 > string2 ]  string1이 string2보다 크면 true


# if [ "$pid" = "" ] ; then

# if [ X$pid != "X" ] ; then

# if [ $HOST != `hostname` ] ; then

# if [ "$MWASTART" > "1" ] ; then

# if [[ $? = 255 ]] ; then


[ exp1 -eq exp2 ]             exp1과 exp2가 같으면 참(equal)

[ exp1 -ne exp2 ]             exp1과 exp2가 같지 않으면 참(not equal)

[ exp1 -lt exp2 ]             exp1이 exp2보다 작으면 참(less than)

[ exp1 -gt exp2 ]             exp1이 exp2보다 크면 참(greater than)

[ exp1 -le exp2 ]             exp1이 exp2보다 작거나 같으면 참(less than or equal)

[ exp1 -ge exp2 ]             exp1이 exp2보다 크거나 같으면 참(greater than or equal)


# if [ $x –ne 0 ] ; then

# if [ $? –eq 0 ] ; then

# if [ "$RWHOD" –eq 1 ] ; then

# if [[ "$rval" –eq ${EXIT_NA} ]] ; then

# while [ ${CNT} –le ${MAX_NISCHECKS} ] ; then

# if [ $# -ge 0 ] ; then

# if [ "$XX" –gt "$YY" ] ; then

# if [ "$X" –lt 1 ] ; then

# if [ $# -ne 1 ] ; then

# if [ `grep $HOSNAME /etc/mail/sendmail.cw|wc –l` -eq 0 ] ; then


( expression )         expression이 참이면 참

! expression           Binary NOT 연산자

exp –a exp2            Binary AND 연산자, 우선순위가 –o 보다 높음.

exp –o exp2            Binary OR 연산자

exp1 && exp2           exp1과 exp2가 모두 참이면 참

exp1 || exp2           exp1가 참이거나 exp2가 참이면 참


# if [ "$GATED" –eq 0 –a "X$pid" = "X" ] ; then

# if [ "$CRON" –eq 1 –a –x /usr/sbin/cron ] ; then

# if [ "$NIS_DOMAIN" –a –f /usr/bin/domainname ] ; then

# if [ "$NIS_MASTER" –ne 0 –o "$NIS_SLAVE" –ne 0 ] ; then

# if [ "$9" = 'S' ] || [ "$9" –lt '2' ] ; then

# if [ "$VTDAEMON_START" –eq 1 ] && [ -x /usr/sbin/vtdaemon ] ; then

# if [[ -r /usr/sbin/swagentd# ]] && [[ -h /usr/sbin/swagentd ]] ; then

# if [ $status !=2 –o –z "$DOMAIN" –o –z "$SERVER" ] ; then

# if (( status == 0 )) && [[ -n $PROTO ]] ; then


l         Integer 표현식


(( integer1 == integer2 ))    integer1과 integer2가 같으면 참

(( integer1 != integer2 ))    integer1과 integer2가 같지 않으면 참

(( integer1 < integer2 ))           integer1이 integer2보다 작으면 참

(( integer1 > integer2 ))           integer1이 integer2보다 크면 참

(( integer1 <= integer2 ))    integer1이 integer2보다 작거나 같으면 참

(( integer1 >= integer2 ))    integer1이 integer2보다 크거나 같으면 참


# if (( $? != 0 )) ; then

# while ((n>0))

# if ((n<2) || !length(part[2])) ; then

# if ( $1 != mypid ) ; then

# if (( $1 > $2 )) ; then


3.Shell Programming


u        if 조건문


if 조건문

then

   명령어

[elif 조건문

then

   명령어]

[else

   명령어]

fi


if 조건문; then 명령어; [elif 조건문; then 명령어;] [else 명령어;] fi


:wq# vi if1.sh

X=hello

if [ $X = hello ]

then

   echo "Welcome"

else

   echo "Goodbye"

fi

:wq

# sh if1.sh

Welcome

# vi if2.sh

if [ -f temp ]

then

   mv temp temp1

elif [ -f temp1 ]

then

   mv temp1 temp2

fi

:wq

# sh if2.sh


u        case 조건문


case 변수 in

변수값1|변수값2…)

   명령어;;

변수값3|변수값4…)

   명령어;;

*)

   명령어;;

esac





#  vi case.sh

case $1 in

-d|-r)

        rmdir $dir1

        echo "directory removed" ;;

-o)

        echo "option -o" ;;

*)     

        echo "Invalid option,Try again..." ;;

esac

:wq

# chmod 777 case1.sh

# ./case.sh -o

option -o


u        while 반복문


while 조건문

do

   명령어

done


- 다음은 모두 같은 while문이다.


while [ 1 ]

do

  echo "Test"

done

while true

do

  echo "Test"

done

while [ : ]

do

  echo "Test"

done

while :

do

  echo "Test"

done


# vi while1.sh

count=$(who|grep -v root|wc -l)

while [ "$count" -gt 0 ]

do

   echo "Users still logged in..."

   sleep 1

   count=$(who|grep -v root|wc -l)

done

:wq

# sh while1.sh


# vi while2.sh

# /usr/bin/sh

#

print -n "Enter a value : "

read Value

print "Thank You"

count=0

while [ "$count" -lt "$Value" ]

do

   (( count=count + 1 ))

   print "Still sleeping for the $count th time..."

   sleep 2

done

print "End of $0"

:wq

# sh while2.sh


u        for 반복문


for 변수 [in 변수값1,변수값2,…]

do

   명령어

done


# vi for1.sh

for name in $(cut -d -f1 /etc/passwd)

do

   mailx $name < message.txt

   echo "Mail sent to $name"

done

:wq

# sh for1.sh

# vi for2.sh

if [[ ! -d "$1" ]]

then

   exit 1

fi

filename=$(ls $1)

for onefile in $filename

do

   if [[ -f ${1}/$onefile ]]

   then

      ll ${1}/$onefile

   elif [[ -d ${1}/$onefile ]]

   then

      ll -d ${1}/$onefile

   fi

done

:wq

# sh for2.sh /etc







u        until 반복문


until 조건문

do

   명령어

done


# vi until.sh

count=$(who|grep -v root|wc -l)

until [ "$count" -eq 0 ]

do

   echo "Users still logged in..."

   sleep 1

   count=$(who|grep -v root|wc -l)

done

:wq

# sh until.sh


u        select 반복문


select 변수 [in 변수값1,변수값2,…]

do

   명령어

done


- select문은 PS3 prompt를 사용한다. PS3 shell 변수의 기본값은 #? 이다.

- 변수는 변수값1,변수값2,… 등이 할당된다.

- 입력된 변수의 값의 숫자는 REPLY라는 shell변수에 저장된다.

- exit,return,break 등의 명령어로 반복문을 빠져나올수 있다.

- [in 변수값1,변수값2,…]가 없을경우에는 Positional Parameter를 사용한다.


# vi edit.sh         ### Edit the file ###

select menu in $(ls) "Exit" ; do

   case $menu in

     Exit) exit;;

     "") echo "Invalid selection. Try again!";;

     *) cp $menu $menu.bak; vi $menu ;;

   esac ; done

:wq





# vi color.sh

  select color in red blue green

  do

     echo "$color is an $color color"

     echo "$REPLY is a REPLY value"

  done

:wq

# sh color.sh

1)red

2)blue

3)green

#? 1

red is an red color

1 is a PEPLY value

#? 2

blue is an blue color

2 is a REPLY value

#? ^C

#


# vi select.sh

PS3="Enter your choice =>"

select menu in "full backup"

                  "partial backup"

do

 case $menu in

 "full backup")

  fbackup –0uf /dev/rmt/0m –i /stand

  echo "Full backup has begun"

  exit 0;;

 "Partial backup")

fbackup –0uf /dev/rmt/0m -i /opt

echo "Partial Backup has begun"

return;;

 *) echo "$REPLY is an invalid

             option. Try again!";;

 esac

done

:wq

# sh select.sh


# vi nest.sh

  #### Nested Select Command Example ###

#! /usr/bin/sh

PS3="Main Choice by number=>"

select menu in "List Files" "Exit"

do

   case $menu in

   "List Files")

      PS3="Sub Choice by number=>"

      select ls_option in "Short" "Long" "Main"

      do

         case $ls_option in

          "Short") lsf;;

           "Long") ll;;

           "Main")

               PS3="Main Choice by number=>"  ## Restore Prompt

               break 1 ;;  ## exit inner loop

           "") echo "$REPLY is an invalid option. Try again!";;

         esac

      done ;;

   "Exit") exit;;

   "") echo "$REPLY is an invalid option. Try again!";;

   esac

done

:wq

# sh nest.sh





u        Function(함수)


function 함수명

{

  shell script

}

함수명()

{

  shell script

}


- shell script안에 선언할수도 있고 밖에 선언할수도 있다.

- 함수명이나 argument로 called될수 있다.

- 같은 process를 반복적으로 사용할때 유리하며 debugging하기가 쉽다.

- typeset -xf name 으로 함수명을 export하여 global 함수로 선언할수 있다.


# vi func1.sh

function exef

{

   if [ -x $1 ]

   then

      echo "$1 is executable"

   fi

}

for file in `ls`

do

   exef $file

done

:wq

# sh func1.sh


# vi func2.sh

Uppercase()

{

   echo $* | tr "[a-z]""[A-Z"]"

}


print -n "Enter in a string:"

read string

upper_string=$(Uppercase $string)

echo "The uppercase string is: $upper_string"

:wq

# sh func2.sh







# vi func3.sh       : Recursive Fuction

bottom_up

{

   typeset SAVEPWD

   echo "\nDirectory being listed is: $PWD\n"

   lsf

   if [ "$PWD" != "/" ]

   then

      SAVEPWD=$PWD

      cd ..

      bottom_up

      cd $SAVEPWD

   else

      echo "That's the end!"

   fi

}

:wq

# sh func3.sh


u        Array(배열)


- shell script에서 사용할수 있는 배열은 1차원배열이다.

- 배열요소(element)는 최대 512-1024까지 쓸수 있다.

- 배열요소는 [0]부터 [1023]까지 쓸수 있다.

- Array subscript인 [N]에서 N은 integer또는 integer expression을 쓸수 있다.


# X[0]=first

# X[1]=second

# X[2]=third

# echo ${X[1]}

second

# echo ${X}         : ${X}는 ${X[0]}과 같음

first

# echo ${X[*]}             : '*'나 '@'는 모든 요소를 가르킴

first second third

# echo ${#X[*]}

3

# i=3

# X[2*(i+1)]=10

# print ${X[8]

10



# set -A YY 100 200 300    : set -A는 변수를 배열로 선언한다.

# print ${YY[0]} ${YY[1]} ${YY[2]}

100 200 300

# set +A YY 150

# print ${YY[@]}

150 200 300




4.Shell Command


u        : 명령어


- ':' 명령어는 아무것도 수행하지 않으며, 어떤 영향도 미치지 않는다. '0'값이 return됨.


# vi xx.sh

if [ -f /opt ]; then

   ls

else

   :            아무것도 수행하지 않는다.

fi

:wq


u        . 명령어


# . /etc/profile


- /etc/profile이라는 프로그램을 수행한다. 이는 sh나 ksh처럼 또하나의 shell을 fork하여

  프로그램을 수행하지 않으며 이 프로그램은 수행가능한 permission이 없어도 된다.

  즉 이 파일은 'x' permission이 없어도 된다.


u        alias 명령어


alias [-x] [ name[=value] … ]


# alias                             : 현재 setting된 모든 alias를 display

# alias a=alias

# a x=lsf

# alias i='

> echo Users logged in are:

> who|sort

> echo I am `whoami`'

# i                                  : alias문을 수행한다.

# unalias i                        : alias변수 i를 unsetting한다.

# unalias -a                       : shell command에서 typing한 모든

                                        alias를 해제한다.

# alias -x who='who|sort'       : Korn shell에서 who를 export하여

                                        subshell에서도 사용가능하다.


u        break 명령어


break [n]


- for,while,until,select문과 같은 반복문에서 exit할 때 사용한다.

- n을 쓰면 n레벨만큼 loop를 exit한다.


# vi break.sh

for file in x y z none

do

   if [ -x $file ]; then

      echo $file

      break

   fi

done

:wq


u        command 명령어


command [arg …]


- argument를 command로서 취급한다.


# command lsf       : lsf를 command로 사용한다.

# command aaa       : aaa를 command로 사용한다.


u        continue 명령어


continue [n]


- for,while,until,select문과 같은 반복문에서 continue이하의 문을 수행하지 않고

다시 시작한다.

    - n을 쓰면 n번째 반복문을 다시 시작한다.


# vi con.sh

for file in x y z

do

   if [ -x $file ]; then

      continue

      echo "$file is executable"

   fi

   echo $file is not executable

done

:wq


u        echo 명령어


echo [arg …]


# echo 'This is a' $var 'example.'

# echo "This is a $var example."

# echo "Enter your user name: \c"

> read user

> echo 'User is' $user


echo 에서 Escape Character

\b     backspace

\c     continue line. new line을

       하지 않고 계속 붙여서 print한다

\f     form feed

\n     new line

\r     carriage return

\t     tab

\v     vertival tab

\\     backslash


u        eval 명령어


eval [arg …]


- argument를 input으로 받아서 명령어로 수행하며 argument는 command나 shell

  script가 될수 있다.


# cmd='ps -ef > ps.out'

# eval $cmd

# eval "grep jones $file|set|echo $1 $2 $3"


u        exec 명령어


exec [arg …]


- 새로운 process나 subshell을 만들어서 argument를 수행하지 않고 현재 shell로

  명령어를 바로 수행한다.

# exec 3< file          file desciptor number 3으로 file을 open한다.

# ecec 2> /dev/null     표준에러를 /dev/null로 출력한다.


u        expr 명령어         # man expr 참조


expr expression {+,-,\*,/} expression

expr expression {=,\>,\>=,\<,\<=,!=} expression

expr string1 : string2


# a=15

# expr $a + 5

20

# count=`expr $count + 5`

# A=batman

# expr substr $A 1 3

bat

# expr index $A m

4


u        fc 명령어


fc [-r] [-e example] [first [last]]

fc –l [-nr] [first [last]]

fc –s [old=new] [first]

fc –e – [old=new] [command]


- fc command는 history file을 list하거나 history file에서 command를 edit할 수있다.


# fc –l            : history file의 내용을 display한다.

# fc –l 20 25

# fc –l 10

# fc –e vi 15 20

# fc –e -          : 방금 실행한 command를 다시 실행한다. # r 명령과 같다.

# fc –e – ls=cd  


u        let 명령어


let "expression"

(( expression ))

- let는 산술 표현을 가능하게 하며 long integer 계산을 한다.


Operator

Description

-

!

/  %

+  -

<  <=  >  >=

==  !=

=

unary minus

logical negation

곱하기,나누기,몫

더하기,빼기

비교

같다,같지 않다

변수 할당


# x=10

# y=2

# let x=x+2

# echo $x

12

# let "x=x/(y+1)"

# echo $x

4

# (( x=x+1 ))

# echo $x

5

# x=12

# let "x<10"

# echo $?

1

# (( x > 10 ))

# echo $?

0

# if (( x > 10 ))

>then echo x greater

>else echo x not greater

>fi

x greater


u        read 명령어


read [-r] name…        : POSIX Shell only

read [-prsu] [name]    : Korn Shell only


-r          라인연속으로 쓰인 라인끝의 \를 해석하지 않는다.

-un         file descriptor n 으로부터 input을 read한다.


# vi read.sh

  while read -r xx yy

  do

     printf "%s %s \n" "$yy" "$xx"

done < input_file

:wq


u        return 명령어


return [n]


- 함수의 실행을 마치고 calling shell script에게 exit status n을 return한다.

- n이 없으면 return status는 함수의 마지막 command의 값이다.

- return이 함수의 밖에서 수행되면 exit로서 실행된다.


# vi return.sh

  search()

  {

     if grep xxx "$1" > /dev/null 2>&1

     then return 1

     else return 2

     fi

  }

:wq

# sh return.sh filename


u      set 명령어


l         Positional Parameter값 setting


# set spring summer fall winter

# echo $3

fall

# echo $*

spring summer fall winter



l         Positional Parameter Sorting


# set third first second

# echo $1 $2 $3

third first second

# set –s               : 값을 lexical order로 sorting함

# echo $1 $2 $3

first second third

# set +s            : unsetting








option         option-name meaning

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

set –a         allexport   모든 parameter가 자동으로 export됨. == set -o allexport

set -C         noclobber   #date>XX시 >로 overwrite하지못하게 함. date>|XX로는 가능

set –e         errexit     shell command fail시 즉시 logout또는 shell을 exit함

set –f         noglob             # ls * 시wild card문자를 인식못함

set –h         trackall   

set –k         keyword    

set –m         monitor     Background jogs이 각각다른 process group에서 수행되고

                           작업이 끝나면 message를 report함

set –o                     set –o monitor와 같이 option-name에 붙여서 옵션을

                           setting함

set –s                     positional parameter를 sort함

set –t                     shell을 exit한후에 command를 수행함

set –u         nounset     substituting시 unset parameter를 error로 취급함

set –v         verbose     command를 display한후 command 수행

set –x         xtrace             command수행시 command와 argument까지 print함.

                           shell script의 debug mode로 사용함.

              

set                        현재 setting된 모든 shell variable을 list함

set -                      -x와 –v option을 turn off하고 flag에 대한 argument

                           검사를 하지 않음

set --                     옵션의 어떤 변화도 하지못하게 함. # set -- -;echo $1

                                      file명으로 시작하는 file을 rm할 경우 # set -- -;rm –aaa


# set –o ignoreeof          : ignoreeof라는 옵션을 turn on

# set +o vi                : vi의 옵션을 turn off

# set –o noglob            : noglob옵션을 turn on 시키고 wild card인

                                    *,[],-,!,? 등을 shell이 해석하지 못하게함

# set –o noexec            : shell의 syntax error를 check하기위해 사용.

                             이 옵션은 interactive shell에서는 사용되지

                                    않으며 shell script에서만 수행됨.

                             noexec 옵션은 실제로 shell을 수행하지 않으면서

                                       shell의 syntax error만을 check하는 명령어다.



# vi set1.sh

  set –o noexec

  echo "This is test

  ls

  cp /aaa /bbb

:wq

# ksh set1.sh

set1.sh: syntax error at line 2 : '"' unmatched

# vi set2.sh

  set –x

  ls

  echo "The Test"

  set +x

  lsf

:wq

# sh set2.sh


u        shift 명령어


shift [n]


shift command는 positional parameter($1,$2,$3..)의 내용을 왼쪽순으로 move한다.


# vi shift1.sh

  yflag=0

  zopt=""

  for arg in "$@"

  do

     if [ "x$arg" = x-y ]

     then

        yflag=1

        shift

     else

       zopt="$2"

       shift 2

     fi

  done

:wq


u        trap 명령어


trap [command] [signal]


- signal 값은 # kill –l또는 # man kill 명령어로 볼수 있음.

# trap "echo 'Command Failed'" 2

                       : ^C(interupt)를 치면 echo 문장이 수행됨.


# trap              : trap 명령을 수행한후 옵션이 없이 trap명령을 수행하면 현재

                    setting된 모든 trap내용을 보여줌

# trap "" 1 2 3

                       : 1}HUP 2)INT 3)QUIT가 입력되도 무시하라.

# trap "echo logout" 0

                       : signal이 '0' 이면 NULL signal로서

                         shell에서 exit할때 command가 수행된다.


u      typeset 명령어


typeset [-][+]옵션  변수명[=변수값]


option      meaning

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

[-]         변수명의 속성을 setting

[+]         변수명의 속성을 turn off

-Ln         왼쪽의 공백을 제거하고 왼쪽에서 n숫자만큼 cut

-Rn         왼쪽에 공백을 채우고 오른쪽에서 n숫자만큼 cut

-Z          오른쪽으로 shift하고, 첫번째 문자가 숫자이고 –L옵션과 같이

            쓰지 않았으면 왼쪽에 숫자0을 채움

-i          변수명을 integer로 선언

-f          변수명이 아니라 함수명으로 변수를 선언

-l          모든 영문대문자를 소문자로 변환

-u          모든 소문자를 대문자로 변환

-r          변수를 read-only로 만듬,즉 변수를 상수로 만듬

-x          변수를 export함, 즉 변수를 전역변수로 만듬

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

# typeset

현재 setting되어있는 변수의 data type을 보여줌

# typeset AA

AA변수를 string변수로 선언,또한 함수내에서 Local변수 즉 지역변수로 선언

하지만, shell에서 변수는 default로 string data type임


# DATA="Today we had very HOT weather"

# typeset –u DATA

# echo $DATA

TODAY WE HAD VERY HOT WEATHER

# typeset +u DATA : DATA변수의 속성을 turn off 

# DATA="as of the "${DATA}

# echo $DATA

as of the TODAY WE HAD VERY HOT WEATHER


# AAA=123456789

# typeset –L3 AAA

# echo $AAA

123


# typeset –LZ X=00005

# print $X

5

# typeset –i X        : 변수X를  integer로 선언 # integer X와 같음

# typeset –i2 X     : 변수X를 2진수로 선언

# typeset –i8 X     : 변수X를 8진수로 선언

# typeset –i10 X    : 변수X를 10진수로 선언

# typeset –i16 X    : 변수X를 16진수로 선언

# typeset -r Y=123  : 변수Y를 readonly변수로 선언 # readonly Y=123과 같음

# typeset -f        : 모든함수와 그 값을 display함

# typeset -xf       : export된 모든함수와 그 값을 display함

# typeset -xf XX    : 함수명 XX를 export하여 global function으로 선언함


u        ulimit 명령어


ulimit  [-f] [n]


- ulimit command는 child process나 subprocess에 의해 사용된는 resources를 제한한다.


# ulimit               : 현재 limit값을 보여준다

# ulimit –f 1000       : 현재process나 향후 process가 write할 수 있는

                          file size를 1000 block(1000*512 byte)으로 제한한다.

# ulimit –f unlimited : child process가 생성할 수 있는 size의 제한을 없앤다.







5.Regular Expression(정규 수식)


u        Pattern Matching과 Regular Expression의 비교 - # man 5 regexp참조


Pattern Matching


Regular Expression

- POSIX shell에서 사용

- file name생성과 case문에서 사용

- UNIX command와 Text Editor에서 사용

  (ed,vi,ex,sed,awk,expr,grep)

- file name을 match한다

- character string을 match한다

- file name을 substitute한다

- string을 search해서 substitute한다

- 사용되는 특수문자

  ?,  *,  [ - ],  !

- 사용되는 특수문자

  .,  [],  -,  ^,  $,  *


u        하나의 문자와 Match - .(dot)


A.          : AB,Ab,AA,A9등과 같이 A다음에오는 어느한문자와 match

...         : 연속된 3문자와 match

# man 5 regexp|col -b|expand > regexp.man

# grep 'RE.' regexp.man       : RE다음에오는 어느한문자와 Match되는 라인만 출력


u        문자의 시작과 Match - ^


^abc        : 첫문자가 abc로 시작되는 문자와 match. abc,abcabc,abcdef등과 match

^C          : 문자의 시작에서 C와 match

^C$         : 하나의 문자 C와 match

^.$         : 하나의 문자로만 구성된 문자와 match

^[ABC]      : 첫문자가 ABC로 시작되는 문자와 match


u        문자의 끝과 Match - $


abc$        : 끝문자가 abc로 끝나는 문자와 match. defgabc,cccabc,abc등과 match

^...$       : 3개의 문자로만 구성된 문자와 match

\.$         : 문자의 끝에서 마침표(.)과 match

\*$         : 문자의 끝에서 (*)와 match



u        문자 Match - []


[Tt]he      : The나 the라는 글자를 search

h[iau]t     : hit,hat,hut의 글자와 match

[ABC]       : A,B,C를 포함하는 문자와 match


u        범위를 포함하는 문자와 Match - [ - ]


[a-z]       : 소문자 a부터 z까지 어느문자와도 match

[0-9]        : 0-9까지 어떤 하나의 숫자와 match

[0-57]      : 0,1,2,3,4,5,7과 match

[a-c5-8X-Z] : a,b,c,5,6,7,8,X,Y,Z중 하나의 문자와 match

[0-3-]      : 0,1,2,3,-와 match


u        Complemented문자 Match - [^  ]


[^ ]        : 공백이 아닌 한문자와 match

[^0-9]      : 0-9까지 숫자가 아닌 하나의 모든문자와 match

[^a-zA-Z]   : 영문 알파벳이 아닌 문자나 숫자와 match

[012^]      : 0,1,2,^와 match

^[^a-z]$    : 소문자을 제외한 나머지 문자중 하나와 match

# man 5 regexp|col -b|expand > regexp.man

# grep '^$' regexp.man|wc -l         : 공백라인수를 출력한다.

# TMOUNT=`/sbin/mount | grep '^/tmp(/| )' | wc -l`

# grep -q -e "^/usr/bin$" -e "^/usr/bin:" -e ":/usr/bin:"\

         -e ":/usr/bin$" /etc/PATH


u        Null 또는 여러 같은문자와 Match - *,+,?


B*          : Null문자,B,BB,BBB...등과 match

AB*C        : AC,ABC,ABBC...등과 match

A+          : A,AA,AAA...등과 match

AB+C        : ABC,ABBC,ABBBC...등과 match

A?          : Null문자 또는 A와 match

AB?C        : AC,ABC와 match

[A-Z]+      : 하나이상의 대문자와 match

(AB)        : AB문자와 match

(AB)+C      : ABC,ABABC,ABABABC...등과 match

AB.*XYZ     : ABXYZ,ABCXYZ,ABCCCCXYZ...등과 match


u        특수문자 Match - \


\*          : 특수문자 *와 match

\$          : 특수문자 $와 match

\\          : 특수문자 \와 match

\\\\\.\*$   : 문자의 끝에서 \\.* 와 match


u        Subexpression - \( ... \)


- \(...\)구문을 사용한다.

- subexpression과 match하는 문자를 recall하기위해 '\숫자'를 사용한다.

- '\숫자' 는 1-9까지 쓸수있다.

- \1 은 1번째 subexpression,\2 는 2번째 subexpression을 나타낸다.


# who

root       console      Oct 23 13:01

root       ttyp1        Oct 27 12:45

root       pts/0        Oct 22 09:03

# who|sed 's/\([^ ][^ ]*\)[^A-Z][^A-Z]*\(.*\)/\2-->\1/'

Oct 23 13:01-->root

Oct 27 12:45-->root

Oct 22 09:03-->root

- 첫번째 /\([^ ][^ ]*\) 는 공백이 아닌 하나이상의 문자와 match하며 뒷부분의

  \1 의 값과 같다.즉, 여기서는 username root를 가르킨다.

- 두번째 \(.*\) 는 최초로 대문자로 시작되는 문자와 match하며 뒷부분의

  \2 의 값과 같다. 여기서는 Oct를 가르킨다.



6.Sed(Stream Editor)


u        sed 형식


sed [-n] command input_file...

sed [-n] [-e command]... [-f script_file]... [input_file...]


-n          화면에 display하지 않는다. 단  p명령어일경우는 화면에 display한다.

            -n옵션은 -e나 -f옵션중 하나와 같이 사용할수 있다.

-e command  command를 editing하며, input file이 없으면 표준입력이 사용된다.

-f script   input file에서 editing command의 script file을 수행한다.


- sed는 입력파일로부터 한라인씩 data를 read한다.

- sed는 default로 화면에 출력을 하며 input file을 modify하지 않는다.


# sed "s/UNIX/Unix/g" file1 > file2.new

# sed -e "s/Miss/Ms/g" -e "s/Mrs/Ms/g" file2

# sed -n "1,10p" file2

# cat script

1,10p

# sed -n -f script file2


u        s(substitute)


[address [,address]] s/string_old/string_new/[flag]


flag        meaning

g           global substitution(전라인을 모두바꾼다)

p           print line

w file      file로 write한다


# sed "s/[Cc]omputer/COMPUTER/g" file1

# sed -e "1,5s/abc/xyz/" -e 's/kbs/mbc/' file1 > file2

# sed "/abcde/s/ab/AB/g" file1

# sed -e 's/abc/xyz/w file2' file1

# sed "3s/the/xyz/g" file1

# sed '3s/^the /xyz/' file1

# sed -e "/the/s/ for /xyz/g

# cat file1| sed "/the/s/ for /xyz/gw file2

# sed "1,8s/aaa/bbb/g" file1 > file2

# sed "/^5/,/^15/s/from/FROM/g"

# sed -e "/^The first time/,/^End of file/s/lsf/ll/g"

# sed "1,$s/\/usr\/bin/\/sbin\/bin/g"


u        d(delete)


# sed "1,10d" fileA

   - fileA에서 1-10라인까지 delete한다.

# sed "/^From/!d" mbox

   - mbox file에서 From으로 시작되는 라인만 제외하고 모두 delete한다.


u        p(print),l(list),=,q(quit),r(read),w(write)


p           standard output에 print한다. -n옵션과 함께써도 print된다.

l           nonprinting문자도 같이 표준출력한다.

=           address 라인의 라인번호를 표준출력한다.

q           현재라인을 출력하고 sed를 종료한다.

r file      file의 내용을 read하여 표준출력한다.

w file      file에 address라인을 write또는 append한다.


# vi cap

   One potato, teo potato,

   three potato, four.

   Five potato, six potato,

   seven potato, more.

:wq


# sed -n "1,2p" cap

One potato, two potato,

three potato, four.


# sed -e "q" cap

One potato, teo potato,

# sed -e "/\./=" -e " /[A-Z]/w file1" cap

One potato, teo potato,

2

three potato, four.

Five potato, six potato,

4

seven potato, more.


# killproc() {

      for x in "$@"

      do

         pid=`ps -e |grep "$x" |sed -e 's/^  *//' -e 's/ .*//'`

         [ ! –z "$pid" ] && echo killing $x && kill $pid &

      done

  }

# findproc() {

    pid=`ps –e |grep "$1" |sed -e 's/^  *//' -e 's/ .*//'`

    echo $pid

  }

# killproc() {           

      echo stopping $1

      pid=`/usr/bin/ps -e |

            /usr/bin/grep "$1" |

            /usr/bin/sed -e 's/^  *//' -e 's/ .*//'`

            [ "$pid" != "" ] && kill $pid

  }

# if [ "$RWHOD" –ne 1 ]; then

      rval=2

  else

      pid=`ps -el | awk '( ($NF ~ /rwhod/) && ($4 != mypid) &&

           ($5 != mypid)) { print $4 }' mypid=$$ `

      if [ "X$pid" != "X" ]; then

         if kill $pid; then

            echo "rwhod stopped"

         else

            rval=1

            echo "Unable to stop rwhod"

         fi

      fi

  fi

#

#

#

# ARRAYMON_PID=`ps -ef | awk '$0 ~ /.*arraymon*/ && $0 !~ /.*awk.*/

                  { print $2 }'`

  if [ "$ARRAYMON_PID" ]

  then

     echo "Killing disk array monitor daemon."

     kill -9 $ARRAYMON_PID

     sleep 2

     ARRAYMON_PID=`ps -ef | awk '$0 ~ /.*arraymon*/ && $0 !~ /.*awk.*/

                     { print $2 }'`

     if [ "$ARRAYMON_PID" ]

     then

       echo "ERROR:  Could not kill ${ARRAY_MONITOR_DAEMON}"

     fi

  fi

#




























7.Shell Program 예제


-shell script를 위한 data file은 다음과 같다.

# vi data

  100 200 300 400

  500 600 700 800

  900 1000 1100 1200

  1300 1400 1500 1600

  1200 800 400 0

:wq

# vi exp1.sh

if [[ ! -f "$1" ]]

then

   echo "${0##*/}"

   exit 1

else

   filename=$1

fi

exec 3< $filename : file descriptor 3으로 filename를 open

typeset -i II=0   : XX를 integer로 선언

while read -u3 AA[0] AA[[1] AA[2] AA[3]

do

   for II in 0 1 2 3

   do

      (( total[II]=${total[II]} + ${AA[II]} ))

   done

print "Subtotal : "

print ${total[*]}

done

print "Total for the four columns are : "

print ${total[@]}

:wq

# sh exp1.sh












#!/usr/bin/sh

######################## /etc/profile ##########################  


trap "" 1 2 3                   

PATH=/usr/bin:/usr/ccs/bin:/usr/contrib/bin

MANPATH=/usr/share/man:/usr/contrib/man:/usr/local/man

if [ ! -d /usr/sbin ]

then

   PATH=$PATH:/sbin

else

   if [ -r /etc/PATH ]

   then

      grep -q -e "^/usr/bin$" -e "^/usr/bin:" -e ":/usr/bin:"\

                -e ":/usr/bin$" /etc/PATH

      if [ $? -eq 0 ]

      then

         PATH=`cat /etc/PATH`

      else

         PATH=$PATH:`cat /etc/PATH`

      fi

   fi

fi

export PATH

if [ -r /etc/MANPATH ]

then

   MANPATH=`cat /etc/MANPATH`

fi

export MANPATH

if [ -r /etc/TIMEZONE ]

then

   . /etc/TIMEZONE 

else

   TZ=MST7MDT       

   export TZ

fi

if [ ! "$VUE" ]; then

   if [ "$TERM" = "" -o "$TERM" = "unknown" -o "$TERM" = "dialup"  \

                         -o "$TERM" = "network" ]

   then

      eval `ttytype -s -a`

   fi

   export TERM

   if [ "$ERASE" = "" ]

   then

      ERASE="^H"

      export ERASE

   fi

   stty erase $ERASE

   trap "echo logout" 0

   cat /etc/copyright

   if [ -r /etc/motd ]

   then

      cat /etc/motd

   fi

   if [ -f /usr/bin/mail ]

   then

      if mail –e

      then echo "You have mail."

      fi

   fi

   if [ -f /usr/bin/news ]

   then news –n

   fi

   if [ -r /tmp/changetape ]

   then

      echo "\007\nYou are the first to log in since backup:"

      echo "Please change the backup tape.\n"

      rm -f /tmp/changetape

   fi

fi

trap 1 2 3

###################### The End ##########################


#!/usr/bin/sh

############# /.profile ################  


set +u

PATH=/usr/sbin:$PATH:/sbin:/home/root

if [ ! "$VUE" ]; then

   if [ "$TERM" = "" ]

   then

      eval ` tset -s -Q -m ':?hp' `

   else

      eval ` tset -s -Q `

   fi

   stty erase "^H" kill "^U" intr "^C" eof "^D" susp "^Z"

   stty hupcl ixon ixoff

   tabs

   echo

   echo "Value of TERM has been set to \"$TERM\". "

   export TERM

   EDITOR=vi

   export EDITOR

fi

set –u

trap "echo 'logout root'" 0

MAIL=/var/mail/root

echo "WARNING:  YOU ARE SUPERUSER !!\n"

export PS1=`hostname`':$PWD# '

############################# The End ##############################





#!/sbin/sh

######################## /sbin/init.d/inetd #######################

PATH=/sbin:/usr/sbin:/usr/bin

export PATH

rval=0

set_return() {

        x=$?

        if [ $x -ne 0 ]; then

                echo "EXIT CODE: $x"

                rval=1  # always 1 so that 2 can be used for other reasons

        fi

}

case "$1" in

start_msg)

   echo "Start Internet services  daemon" ;;

stop_msg)

   echo "Stopping Internet services daemon" ;;

'start')

   if [ -f /etc/rc.config ]; then

      . /etc/rc.config

   else

      echo "ERROR: /etc/rc.config defaults file MISSING"

   fi

   mask=`umask`

   umask 000

   [ -x /usr/sbin/inetd ] && /usr/sbin/inetd $INETD_ARGS

   if [ $? -eq 0 ]; then

      echo "Internet Services started"

   else

      echo "Unable to start Internet Services"

   fi

   umask $mask

   ;;

'stop')

   if [ -f /etc/rc.config ]; then

      . /etc/rc.config

   else

      echo "ERROR: /etc/rc.config defaults file MISSING"

   fi

   /usr/sbin/inetd -k

   set_return

   if [ $rval -eq 0 ]; then

      echo "Internet Services stopped"

   else

      echo "Unable to stop Internet Services"

   fi

   ;;

*)

   echo "usage: $0 {start|stop}"

   rval=1

   ;;

esac

exit $rval

############################ The End ##############################3

#!/sbin/sh

############# /sbin/rc ################      


arg=$1

arg2=$2

PATH=/sbin

export PATH

/sbin/stty clocal icanon echo opost onlcr ixon icrnl ignpar 2> /dev/null

umask 022

get_scripts() {

   state=$1

   mode=$2

   dir=/sbin/rc${state}.d

   ls $dir 2>/dev/null |

   while read name

   do

      case $name in

      ${mode}*)

         path=$dir/$name

         if [ "$mode" = "S" ]; then

            desc=`$path start_msg`

         elif [ "$mode" = "K" ]; then

            desc=`$path stop_msg`

         fi

         echo $path $desc

     esac

  done

}

if [ -f /sbin/rc.utils ]; then

   . /sbin/rc.utils

else

   init_list()

   {

      echo $1

   }

   add_list()

   {

      eval $1

   }

   run_list()

   {

      :

   }

fi

# If /etc/rc.config contains default information (first boot),

# /sbin/auto_parms will invoke /sbin/set_parms to remedy the situation.

# For 10.0 release, the default HOSTNAME is unset or an empty string.

# Assume a timezone if /etc/TIMEZONE does not exist.

TZ=EST5EDT

if [ -f /etc/rc.config ]; then

   . /etc/rc.config

   if [ -x /sbin/auto_parms ]; then

      /sbin/auto_parms

   else

      echo "\nWARNING: /sbin/auto_parms does not exist"

      echo "DHCP invocation skipped."

   fi

else

   echo "\nWARNING: /etc/rc.config does not exist"

   echo "System name not set, default $TZ assumed."

fi

export TZ

# Set runlevel information

set `who -r` x

new=$7         # new run level

old=$9         # previous run level

# Check to see if we are run from /etc/inittab, or from the command line.

# If run from the command line, set the old run-level to the new run-level.

if [ $PPID != 1 ]; then

   old=$new

   # If the new run-level was specified on the command line,go to that state

   # instead.

   if [[ -n $arg2 ]]; then

      new=$arg2

   fi

fi

if [ "$new" = S ]; then

   new=0

   tosingle=1

else

   tosingle=0

fi

BOOT=0

if [ "$old" = S ]; then

   old=0

   BOOT=1

fi

# Process scripts

found=0

if [ "$new" -gt "$old" ]; then

   # new run level is higher than old, so run start scripts in

   # all intermediate run levels and in new run level.

   if [ $BOOT = 1 ]; then

      init_list "HP-UX Start-up in progress"

   else

      init_list "Transition to run-level $new in progress"

   fi

   typeset -i lvl=$old

   lvl=lvl+1

   while [ $lvl -le "$new" ]; do

      get_scripts $lvl S |

      while read name descrip; do

         if [ -s "$name" ]; then

            add_list "$name start" "$descrip"

            found=1

         fi

      done

      lvl=lvl+1

   done

elif [ "$new" -lt "$old" ]; then

   # new run level is lower than old level, so run kill scripts

   # in all intermediate levels and in new level.

   if [ "$new" = 0 ]; then

      init_list "System shutdown in progress"

   else

      init_list "Transition to run-level $new in progress"

   fi

   typeset -i lvl=$old

   lvl=lvl-1

   while [ $lvl -ge "$new" ]; do

      get_scripts $lvl K |

      while read name descrip; do

         if [ -s "$name" ]; then

            add_list "$name stop" "$descrip"

            found=1

         fi

      done

      lvl=lvl-1

   done

   # If we're ending up in state 0 or S, run the start scripts for

   # that state.

   if [ "$new" = 0 ]; then

      get_scripts 0 S |

      while read name descrip; do

         if [ -s "$name" ]; then

            add_list "$name start" "$descrip"

            found=1

         fi

      done

   fi

else

   # old and new run levels are the same.  Assume that execution

   # is from the command line and run start scripts for the current

   # run level

   init_list "Starting subsystems for run-level $new"

   get_scripts ${new} S |

   while read name descrip; do

      if [ -s "$name" ]; then

         add_list "$name start" "$descrip"

         found=1

      fi

   done

fi

if [ $found = 1 ]; then

   if [ "$BOOT" = 1 ]; then

      run_list boot

   else

      run_list

   fi

fi

if [ "$new" = 0 ]; then

   case $arg in

   "shutdown")

      exec /sbin/sh

      ;;

   "reboot")

      /sbin/reboot

      ;;

   "off")

      /sbin/reboot -h

      ;;

   esac

   #If transitioned to real state 0 (that is, not state S) via init, halt.

   if [[ $PPID -eq 1 && "$tosingle" -ne 1 ]]; then

      /sbin/reboot -h

   fi

fi

# Output message to indicate completion

echo

if [ $BOOT = 1 ]; then

   echo "The system is ready."

else

   echo "Transition to run-level $new is complete."

fi

############################## The End #################################3




















#!/sbin/sh

##################### /sbin/init.d/net ##########################

#

# net:  configure lan interface(s) at initialization time.

# /etc/rc.config.d/netconf defines the configuration parameters:

#

# INTERFACE_NAME[i]:      network interface name (e.g., lan0)

# IP_ADDRESS[i]:          IP address of your system in decimal dot format

# SUBNET_NETMASK[i]:     subnetwork mask in decimal dot format

# BROADCAST_ADDRESS[i]:  broadcast address (other than default) in decimal

#                             format

# LANCONFIG_ARGS[i]:      lanconfig(1m) options (e.g., ieee, ether)

# LOOPBACK_ADDRESS:       loopback address (always 127.0.0.1)

#

# ROUTE_DESTINATION[i]:  route destination

# ROUTE_MASK[i]:       subnet mask

# ROUTE_GATEWAY[i]:       local or remote IP address of gateway

# ROUTE_COUNT[i]:         zero for local gateway, one for remote gateway

# ROUTE_ARGS[i]:          route command options and arguments

#

###########################################################################


set +u  

export PATH=/sbin:/usr/sbin:$PATH

NETCONF=/etc/rc.config.d/netconf

NETSTAT_DATA=/var/adm/netstat_data

OKAY=0

ERROR=1

WARNING=2

# $1 = name of array

# return highest array element index in env; return -1 if no elements

function maxindex {

   # find only lines that start with "var[...]=", grab only the number

   # between "[...]", and print only the last one.

   # we would like to use `sed` as follows:

   #    typeset i=$(set | sed -n 's/^'$1'\[\([[:digit:]]\{1,\}\)\]=.*$/\1/p'

   #                | tail -1)

   # but it is not guaranteed to be in a mounted file system at this time.

   typeset line

   typeset i=-1

   set | while read line; do

      # strip "var[" and "]=...", leaving only number between "[...]"

      line=${line#*$1\[}

      line=${line%%\]=*}

      # if line is all digits, we found "var[...]=...",

      # and line is string between "[...]"

      if [[ -n $line && -z ${line##*([[:digit:]])} ]]; then

         i=$line

      fi

   done

   print -- $i

   return 0

}

##########

#  main   #

##########

case $1 in

start_msg)

   print "Configure LAN interfaces"

   exit $OKAY

   ;;

stop_msg)

   print "Unconfigure LAN interfaces"

   exit $OKAY

   ;;

stop)

   exit $OKAY

   ;;

start)

   ;;  # fall through

*)

   print "USAGE: $0 {start_msg | stop_msg | start | stop}" >&2

   exit $ERROR

   ;;

esac

###########

#  start  #

###########

# Remove the existing /var/adm/netstat_data file.  The first time

# netstat is executed, a new /var/adm/netstat_data file will be

# created.

rm -f $NETSTAT_DATA

# Get actual configuration

if [[ -f $NETCONF ]]; then

   . $NETCONF               # display any errors

   if (($? != 0)); then

      # NB: this is not working as expected:  status is not propagated!

      print "ERROR:   Incorrect data in the file $NETCONF." >&2

      exit $ERROR

   fi

else

   print "ERROR:   Missing the file $NETCONF." >&2

   exit $ERROR

fi

rval=$OKAY

# Do ifconfig and lanconfig commands for each interface

# `foo=$(print $foo)` collapses whitespace, remove surrounding whitespace

# We can have __fewer__ IP_ADDRESSes than INTERFACE_NAMEs (interfaces to be

# ignore).  We can also have __fewer__ SUBNET_MASKs, BROADCAST_ADDRESSes and

# LANCONFIG_ARGS (defaulted).  But we cannot have __more__.

# sanity check

nIF=$(maxindex INTERFACE_NAME)

if (($(maxindex IP_ADDRESS) > nIF)) || \

   (($(maxindex SUBNET_MASK) > nIF)) || \

   (($(maxindex BROADCAST_ADDRESS) > nIF)) || \

   (($(maxindex LANCONFIG_ARGS) > nIF))

then

   print "WARNING: Missing INTERFACE_NAME for corresponding IP_ADDRESS, SUBNET_MASK," >&2

   print "         BROADCAST_ADDRESS or LANCONFIG_ARGS in the file" >&2

   print "         $NETCONF.  Excess variables will be ignored." >&2

   rval=$WARNING

fi

i=0

while ((i <= nIF)); do

   NAME=$(print ${INTERFACE_NAME[i]})

   INTERFACE_NAME[i]=$NAME          # without whitespace for route tests below

   IP=$(print ${IP_ADDRESS[i]})

   IP_ADDRESS[i]=$IP                 # without whitespace for route tests below

   if [[ $IP = "RARP" ]]; then

      IP=`/usr/sbin/rarpc $NAME`

      IP_ADDRESS[i]=$IP              # without whitespace for route tests below

   fi

   if [[ -n $NAME && -n $IP ]]; then

      MASK=$(print ${SUBNET_MASK[i]})

      [[ -n "$MASK" ]] && MASK="netmask $MASK"

      BCAST=$(print ${BROADCAST_ADDRESS[i]})

      [[ -n "$BCAST" ]] && BCAST="broadcast $BCAST"

      PROTO=$(print ${LANCONFIG_ARGS[i]})    # do not set PROTO to any default

      emsg=$(ifconfig $NAME $IP $MASK $BCAST up 2>&1)

      status=$?

      if ((status == 0)) && [[ -n $PROTO ]] ; then

         emsg=$(lanconfig $NAME $PROTO 2>&1)

         status=$?

      fi

      if ((status != 0)); then

         print "ERROR:   $NAME interface: $emsg" >&2

         rval=$ERROR

      fi

   fi

   let i=i+1

done

IP=$(print $LOOPBACK_ADDRESS)

if [[ -n $IP ]]; then

   emsg=$(ifconfig lo0 $IP up 2>&1)

   if (($? != 0)); then

      print "ERROR:   lo0 interface: $emsg" >&2

      rval=$ERROR

   fi

else

   print "ERROR:   Missing LOOPBACK_ADDRESS in the file $NETCONF." >&2

   print "         lo0 interface not initialized." >&2

   rval=$ERROR

fi

# Do route command for each configured route

# Note:  ${IP_ADDRESS[i]} must have whitespace removed already (above)

# We must have the __same__ number of ROUTE_GATEWAYs as ROUTE_DESTINATIONs.

# But we can have __fewer__ ROUTE_COUNTs and ROUTE_MASKs (defaulted).

n=$(maxindex ROUTE_DESTINATION)

if (($(maxindex ROUTE_GATEWAY) != n)) || \

   (($(maxindex ROUTE_COUNT) > n))

then

   print \

      "WARNING: Missing ROUTE_DESTINATION for corresponding ROUTE_GATEWAY" >&2

   print "         or ROUTE_COUNT in the file $NETCONF." >&2

   print "         Excess variables will be ignored." >&2

   rval=$WARNING

fi

i=0

while ((i <= n))

do

   DEST=$(print ${ROUTE_DESTINATION[i]})

   GWAY=$(print ${ROUTE_GATEWAY[i]})

   if [[ -n $DEST && -n $GWAY ]]; then

      COUNT=$(print ${ROUTE_COUNT[i]})

      if [[ -z $COUNT ]]; then

         # default COUNT:  if GWAY is one of the local interface IP

         # addresses, count is 0; otherwise, count is 1.

         COUNT=1

         k=0

         while ((k <= nIF)); do

            if [[ $GWAY = ${IP_ADDRESS[k]} && -n ${INTERFACE_NAME[k]} ]]; then

               COUNT=0

               break;

            fi

            let k=k+1

         done

      fi

      ARGS=${ROUTE_ARGS[i]}

      MASK=$(print ${ROUTE_MASK[i]})

      if [[ -z $MASK ]]; then

          # No subnet mask

          if [[ -z $ARGS ]]; then

             # No arguments

             emsg=$(route add $DEST $GWAY $COUNT 2>&1)

          else

             # With arguments

             emsg=$(route $ARGS add $DEST $GWAY $COUNT 2>&1)

          fi

      else

         # Subnet mask has been entered.

         if [[ -z $ARGS ]]; then

            # No arguments

            emsg=$(route add $DEST netmask $MASK $GWAY $COUNT 2>&1)

         else

            # With arguments

            emsg=$(route $ARGS add $DEST netmask $MASK $GWAY $COUNT 2>&1)

         fi

      fi

      # ignore "entry in use" errors.  these can arise because we

      # booted via NFS diskless, which added routes already

      if (($? != 0)) && [[ -n ${emsg##*entry in use*} ]]; then

         print "ERROR:   $emsg" >&2

         rval=$ERROR

      fi

   fi

   let i=i+1

done

# add loopback route for local interfaces to improve performance

k=0

while ((k <= nIF))

do

   if [[ -n ${IP_ADDRESS[k]} && -n ${INTERFACE_NAME[k]} ]]; then

      emsg=$(route add ${IP_ADDRESS[k]} $LOOPBACK_ADDRESS 0 2>&1)

      if (($? != 0)) && [[ -n ${emsg##*entry in use*} ]]; then

         print "ERROR:   $emsg" >&2

         rval=$ERROR

      fi

   fi

   let k=k+1

done

exit $rval

##################### The End  ###########################

2007/10/27 02:50 2007/10/27 02:50
Posted
Filed under About Knowledge/OS_Unix

Korn Shell

콘셀의 메타 캐릭터

 ~ (Tilde) -- >  현재 유저의 홈 디렉토리를 지칭

 cd ~/dir1

 pwd
 
  --> export/home/user1/dir1


passwd -e --> 기본쉘 변경


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

 cd ~user2

 pwd

  --> /export/home/user2

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

 - (Dash) -- > 이전 작업 디렉토리

 cd

 pwd

  --> /export/home/user1

 cd /tmp

 pwd
 
 --> /tmp

 cd -

 --> /export/home/user1

 cd -

 --> /tmp

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

 * (Asterisk) --> 해당하는 한개 이상의 캐릭터

 cd

 ls f* 

 ls d*

 ls *3

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

 ? (Question mark) --> 한개의 캐릭터에 대응

 ls dir?


----------------------------------------------------------
 
 [] (Square Bracket)  --> 범위를 지칭

 ls [a-f]*    시작 캐릭터가 a-f 까지 해당


 ls [fp]*     f 혹은 p로 시작하는 모든 것

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

 '   ' (single quotes)  --> 이 안에 들어있는 문자는 원래의 의미를 상실한다.

 echo '$SHELL'
 
 -------------------------------------------------------------

 "   " (double quotes)  -->  싱글 쿼트와 비슷하지만 일부 메타문자는 원래의 의미를 가진다.

                            
 echo "$SHELL"

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

 \ (Back slash) -- > 바로 뒤에 오는 문자의 의미를 삭제하고 일반 문자로 인식시킨다.

 echo "\$SHELL"

---------------------------------------------------------------
 
 `  `  (Back quotes)  --> 파이프와 유사한 기능으로서 앞에 오는 명령어의 아규먼트로 작용시킨다.

 echo "Today's date is `date`"


 echo "The user is currently in the $(pwd) directory."


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


리다이렉션 기호 ( <   ,   >  ,     >> )

0 -- stdin ( standard input) <

1 -- stdout ( 스탠다드 아웃풋) >

2 -- stderr ( 스탠다드 에러 ) >


형식

1.   인풋 -- 명령 <  파일명     =      명령 0< 파일명  

2.   아웃풋 -- 명령 > 파일명    =      명령 1> 파일명

3.   덮어쓰기 방지  명령 >>  파일명

4.   에러 재지정   명령 2>  파일명

ls -l > file1; cat file1


echo "that's my directory_list file" >> file1; cat file1


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

변수 -- 쉘에서 필요한 데이터를 저장하는 메모리 영역

set : 현재 쉘의 변수

PS1 : 쉘 프롬프트가 저장된 변수. 이 변수의 데이터가 쉘의 프롬프트로 사용

      수정하게 되면 쉘의 프롬프트가 변경된다.

print $PS1

PS1="$LOGNAME@'UNAME -n'$"


ILU="I like UNIX"

ps1="$ILU >"

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

PATH -- 실행 파일이 있는 경로명을 저장한다.
         
        같은 이름을 가진 명령어가 여러개의 디렉토리에 존재할 수 있고
       
        이 경우 PATH 변수에 있는 경로명의 순서대로 명령어를 찾다가 명령어가 발견된

        경로의 명령어를 실행.
  
        저장되는 데이터는 명령어가 있는 디렉토리의 경로명 , 명령어를 찾을 디렉토리의 순서

echo $PATH


PATH=$PATH:~

echo $PATH

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

HOME -- 사용자의 홈 디렉토리의 절대경로명을 가지고 있다.

print $HOME

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

PWD  -- 현재 명령어를 실행하는 디렉토리의 절대 경로명을 가지고 있다.

print $PWD

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

LOGNAME -- 사용자의 로그인 이름을 저장하고 있다.

print $LOGNAME

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

HOSTNAME -- 사용자가 로그인한 시스템의 이름을 저장

print $HOSTNAME


PS1="$LOGNAME@$HOSTNAME\ $"

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

이전 명령어 목록

  최근에 사용했던 명령어를 실행하기 위한 명령으로 ~/.sh_history = $HOME/.sh_history


명령은 history

옵션

-[nunber] :  최근 출력되는 명령어의 갯수를 변경시키는 옵션


-r  :  최근 실행한 명령을 역순으로 출력

-n  : 출력형태에서 숫자는 없이 명령어만 한줄에 한개씩 출력

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

r  -- 히스토리 명령을 통해서 최근 실행한 명령어의 목록을 다시 실행하기 위해서 사용


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

콘셀의 기능제어

set -o [옵션 네임] 활성화

set +o [옵션 네임] 비활성화

---------------------------------------------
출력 재지정 덮어쓰기 방지

출력재지정을 명시한 파일이 있을 경우 파일이 존재한다는 메시지를 제공하고 명령어를 실행하지 않는다.

set -o noclobber

set +o noclobber

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

파일 이름 완성과 명령행 편집

잘못된 글자만을 수정하는 기능을 명령행 편집기능이라 한다.

일부 경로명 이후의 나머지 경로명을 완성하는 기능을 파일 이름 완성 기능

set -o vi|emacs

set +o vi|emacs


사용법

명령행 편집

esc 적용 ,  k  , j     h, l 

자동완성 기능

명령어 입력후 esc -->\   를 눌러준다.   만약에 경로명이 두개 이상이여서 인식하지 못한다면

구분이 가능한 문자까지 입력후 \

검색을 하려면 esc --> =



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

쉘의 설정 파일

1. /etc/profile   모든 사용자들이 로그인 할때 읽는다.

2. ~/.profile    콘셀이 로그인 셀로 지정된 사용자가 로그인할 때 홈 디렉토리에 파일이 있으면 읽는다.

3. ~/.kshrc      콘셀이 로그인 셀로 지정된 사용자가 로그인할 때 ~/.profile 파일에서 설정이 되어
               
                  있으면 읽는다.


~.profile 로그인 쉘이 본셀이나 콘쉘로 되어 있는 사용자가 읽는 파일,  콘셀에서 추가된 기능은 본쉘이 알 수 없 기
      
          때문에 본 쉘의 기능을 기준으로 설정한다.

~.kshrc   .profile 에 ENV=~/.profile 가 설정되어 있어야 읽고 콘셀만 읽는 파일이기 때문에 콘셀의 기능과 옵션등

           에 대한 설정이 되어 있다.


예제 :

1.사용자 초기화 파일(ksh 사용자)

# vi /.profile
--------------------------------------------------------------------
PATH=/usr/bin:/usr/sbin:/usr/ucb
PS1='$PWD]# '
EDITOR=vi
ENV=~/.kshrc 

export PATH PS1 EDITOR ENV

stty erase ^H
---------------------------------------------------------------------
EDITOR 변수는 시스템 기본 편집기를 변경하는 변수로서
텍스트 환경(console mode)에서의 기본 편집기는 ed(line editor)이고
GUI 환경에서는 text note 프로그램이 기본 편집기 이므로 이를 변경
하고자 할때 사용하는 변수

ENV 변수는 ksh의 경우 2개의 초기화 파일을 가지고 있고, 2번째 초기화
파일을 active로 만들기 위해 사용하는 변수이다.

stty는 터미널 설정에 설정되어 있는 값정보를 변경할 경우 사용하는
명령이고, 지우는 키는 유닉스상에서 Delete키 이므로 이를 변경하기
위해 erase 키를 사용하여 ^+H (Back space)로 변경하였다.

# vi /.kshrc
---------------------------------------------------------------------
set -o vi

alias ls='ls -F'
------------------------------------------------------------------

콘쉘 설정파일


vi .profile
PATH=/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/usr/ccs/bin:/usr/ucb:~
MANPATH=/usr/share/man:/usr/local/man
EDITOR=vi
LANG=ko
ENV=~/.kshrc
export PATH MANPATH EDITOR LANG ENV



vi .kshrc
stty erase ^H ---> ctrl + h
alias ls='ls -aF'
alias c=clear
alias h=history
alias cp='cp -i' 
set -o vi 
set -o noclobber 
PS1='[$PWD]# '
export PS1

2007/10/27 02:29 2007/10/27 02:29
Posted
Filed under About Knowledge/OS_Unix
아쉽게도 구한 자료가 영어 입니다.

천천히 보도록 하겠습니다. 


====================================================================
Just want to deal with a certain shells here ya go.

The Bourne Shell

The Korn Shell

BASH

The Z Shell

The TC Shell

The C Shell

The table for the shell prompt variables

That part covers just basic prompt changing. You can also add colors to your prompt. Provided your terminal supports them. Some of the color information.

The color prompts section

The ANSI color table

Text background colors

Attributes

How to color the different shells:

The Bourne Shell

The Korn Shell

BASH

The Z Shell

The TC Shell

The C Shell

And the lazy shell change:

The Interactive Non Login Shell

The Bourne Shell

The Korn Shell

BASH

The Z Shell

The TC Shell

The C Shell

Finally the lazy prompt change:

The Lazy Prompt Change

The Bourne Shell Lazy Prompt Change

The Korn Shell Lazy Prompt Change

The BASH Lazy Prompt Change

The Z Shell Lazy Prompt Change

The TC/C Lazy Prompt Change

========================================================================================== How to change your shell prompt.

In my last article I discussed how to change your shell. Now let's change your prompt to make it helpful.
Here are what some of my prompts look like:

brendhan@TheBaron>$ <--My Bourne shell
James@TheBaron:/home/James> <-- My Korn shell
[bhorne@TheBaron:bhorne, 10:00 PM, Wed Nov 27] $ <-- My BASH shell
TheBaron darcon /home/darcon[11:17PM]$ <-- My Z shell
[10:02pm] TheBaron[/root] > <--My TC shell
louis@TheBaron /home/louis -> <-- My C shell
Making a custom shell prompt is not to difficult. Some shells have a lot more options than others. First find out what type of shell you have:

<` ="shell"> echo $SHELL

/bin/sh : This is the Bourne shell.
/bin/ksh93 : This is the Korn shell.
/bin/bash : This is the Bash shell.
/bin/zsh : This is the Z shell.
/bin/csh : This is the C Shell.
/bin/tcsh : This is the TC Shell

Now let us deal with the files you will need to edit:

For Bourne it is: .shrc
For Korn it is: .kshrc or .profile
For Bash it is: .bashrc or .bash_profile
For Z it is: .zshrc
For C it is: .cshrc
For TC it is: .tcshrc or .cshrc

Okay now lets deal a little with the shells.
All edits of files shown here take place in the home directory. If you are not sure if you are in your home directory do this:

cd ~

That will take you to your home directory. You can then do this:

pwd

To see what is your home directory.
The quick link section. You can fast forward right to the part you want if you really don't want to read the whole thing.
Bourne Shell
Korn Shell
BASH
Z Shell
TC Shell
C Shell
The Prompt Table
Color Prompts
ANSI Color Codes
Bourne Color
Korn Color
BASH Color
Z Color
TC Color
C Color
Lazy Shell Change
Bourne Shell
Korn Shell
BASH
Z Shell
TC Shell
C Shell
Lazy Prompt Change
Bourne Shell
Korn Shell
BASH
Z Shell
TC/C Shell

The Bourne Shell:

The most limited of the shells. You can only create one set of options for it. Edit your .profile file and you will see this:

# # set prompt: ``username@hostname$ ''
# PS1="`whoami`@`hostname | sed 's/\..*//'`>"
# case `id -u` in
# 0) PS1="${PS1}# ";;
# *) PS1="${PS1}$ ";;
# esac

Remove the comment marks(#) and make it look like this:

# # set prompt: ``username@hostname$ ''
PS1="`whoami`@`hostname | sed 's/\..*//'`>"
case `id -u` in
0) PS1="${PS1}# ";;
*) PS1="${PS1}$ ";;
esac

Your Bourne shell will resemble this:

whoami@hostname>$
the next time you log in. That is about it for the Bourne shell. I have been researching it and there is something called "xcd" that you can use to make it more custom but it is dependant on what version of the Bourne shell you have. Finding out what version you have is really difficult. I did not try this "xcd" setup. If you can help explain xcd in human terms so that I can understand it I may add it

The Korn Shell:

You will want to edit either your .profile or .kshrc file. If you do not have a .kshrc in your home directory don't worry. You can always create one. Korn shell will go to the .profile if you do a full login and goes to .kshrc if you are just using Korn as an interactive shell (This statement is confusing and I will explain more later).

Now you can leave your .profile pretty much as is and just change the existing PS1 line to look like this:

PS1=`logname`@`hostname -s`:'$PWD>' # set the prompt to display the current directory

Your Korn shell will resemble this:

whoami@hostname:current working directory>

BASH:

You will want to edit either your .bash_profile or .bashrc file(Interactive non login shell want .bashrc explain more on this later).You will want to add this line if you don't already have it,

PS1="[\u@\h:\W, \@, \d]> " #custom prompt options

whoami@hostname\current working directory\time\date

Z Shell:

You will want to edit your .zshrc. If you don't have one you can make one:

ee .zshrc

You can add this line to it. Hell it is the only line in mine.

PROMPT=$'%m %n %/[%t]$' # Custom Prompt settings

hostname whoami home directory [time]$

The TC Shell:

You will want to edit your .tcshrc file. If you don't have one you can create one. And it is really nice because all you have to do is copy your .cshrc file:

cp .cshrc .tcshrc

Ok now add this line after the line that says "# An interactive shell -- set some stuff up":

set prompt = " %B[%@]%b %m[%/] >" #Custom Prompt settings

start bold[time] end bold hostname [current working directory] >

The C Shell:

You will want to edit your .cshrc file. You will want to add after the line that says "# An interactive shell -- set some stuff up":

set prompt="`whoami`@`hostname -s` $cwd ->" #Custom Prompt settings

whoami @ hostname current working directory ->

Finish file edit:

After you have edited the files logout and then log back in. This should show you your custom prompt.
Now a small note FreeBSD does not separate the binaries for TC or C. If you place a .tcshrc file in your home directory it will always take precedence over a .cshrc file. Basically you can run a csh command for a prompt but what you are really doing is running TC with limited parameters. If you want to run a true (ok a close to true) C shell do not place a .tcshrc file in the home directory.

Not my style:

What you don't like the options I showed you for your prompt. Fine be that way! I am taking my ball and going home. But I will leave you this really nice table that shows you a lot of the options. Please note the Bourne shell does not have a column because it is a finicky narrow minded shell(and I am not so smart as to be able to figure all of it's unique issues yet).

The Table

:
Description csh* ksh bash tcsh* zsh
Current working directory $CWD $PWD \w %/ %/
Current working directory, with one's home directory by `~' $CWD:t $PWD##*/ \W %~ %~
Full hostname 'uname -n' 'uname -n' N/A %M %M
Hostname up to the first '.' `hostname -s` `hostname -s` \h %m %m
Start (stop) boldfacing mode %B (or %b) N/A N/A %B (or %b) %B (or %b)
Start (stop) standout mode %S (or %s) N/A N/A %S (or %s) %S (or %s)
Start (stop) underline mode %U (or %u) N/A N/A %U (or %u) %U (or %u)
User name `whoami` `logname` \u %n %n
The shell's tty that the user is logged in on %l N/A N/A %| %|
The current history number %h N/A \! %h (or %!) %h (or %!)
Name of the shell N/A N/A \s N/A N/A
Time of day in 12-hour hh:mm AM/PM %t N/A \@ %t (or %@) %t (or %@)
Time of day in 24-hour hh:mm %T N/A \A %T %T
Time of day in 12-hour with seconds hh:mm:ss AM/PM %p N/A \T %p N/A
Time of day in 24-hour with seconds hh:mm:nn %P N/A \t %P %*
The day in 'dd' format %D N/A N/A %D N/A
The month in 'Mon' format %w N/A N/A %w N/A
The month in 'mm' format %W N/A N/A %W N/A
The year in 'yy' format %y N/A N/A %y N/A
The year in 'yyyy' format %Y N/A N/A %Y N/A
The date in "Weekday Month Date" format N/A N/A \d N/A N/A
The date in day-dd format N/A N/A N/A N/A %w
The date in Mon/dd/yy format N/A N/A N/A N/A %W
The date in yy-mm-dd format N/A N/A N/A N/A %D
The weekday in 'Day' format %d N/A N/A %d N/A
Description csh* ksh bash tcsh* zsh

*TC and C shell use the same binaries in FreeBSD that means there really isn't a true C shell but that is a whole different topic. Read further in this article you will get a better explanation.
Okay this list is not complete by any means what so ever but I am one person who has to work for a living.If you know of a variable that can be added let me know by adding a comment here. Remember this is for newbies.

Okay so now you have the basic idea behind how to customize a prompt but it can get even fancier.

Color Prompts

Well this will certainly test my HTML to transfer ANSI color codes to an HTML page. But enough of my babbling. Lets give that prompt some color.

PS1="\[\033[42m\]\[\033[30m\][\[\033[31m\]\u@\[\033[1;33m\]\h:\[\033[1;35m\]\W,\[\033[1;34m\] \@,\[\033[1;37m\]\d\[\033[30m\]]\[\033[0m\]>"

Place that puppy in your .bash_profile as one long line and login and don't call me about how you went blind. And no I don't know how to color coordinate but that prompt shows you some of the fun you can have with a prompt if you are working in an environment that supports colors.

[bhorne@TheBaron:bhorne, 10:56 PM,Sun Dec 01]>$


  ANSI Color Codes  
Color Code Sample
Black 0;30 PROMPT
Red 0;31 PROMPT
Green 0;32 PROMPT
Brown 0;33 PROMPT
Blue 0;34 PROMPT
Purple 0;35 PROMPT
Cyan 0;36 PROMPT
Light Gray 0;37 PROMPT
Dark Gray 1;30 PROMPT
Light Red 1;31 PROMPT
Light Green 1;32 PROMPT
Yellow 1;33 PROMPT
Light Blue 1;34 PROMPT
Pink 1;35 PROMPT
Light Cyan 1;36 PROMPT
White 1;37 PROMPT

  Text Background Colors  
Color Code Sample
Red 0;41 PROMPT
Green 0;42 PROMPT
Brown 0;43 PROMPT
Blue 0;44 PROMPT
Purple 0;45 PROMPT
Cyan 0;46 PROMPT
Gray 0;47 PROMPT

  Attributes  
Attribute Code Sample
Normal Display 0 PROMPT
*Bold 1 PROMPT
Italics 3 PROMPT
Underline 4 PROMPT
*Blink on 5 ?
*Black Outline 6 PROMPT
Reverse Video on 7 PROMPT
*Non display 8 This is suppose to make text invisible on a colored background
*Strike through 9 PROMPT
*Bold off 22 Read Below
*Italics off 23 Read Below
*Underline off 24 Read Below
*Blink off 25 Read Below
*Inverse off 27 Read Below
*Strike through off 29 Read Below


* Bold : The effect is not as dramatic as shown it basically makes the prompt a little brighter.
* Blink on: Warning people find this extremely obnoxious. Don't do it on a public machine.
* Black Outline: This is so faint you really have to look to be able to see it It does not show up like you see in the image. Also it only works with colored backgrounds.
* Non display: The official definition is this: The 8m invisible video sequence does not change the background color. In the ANSI.sys driver, this escape sequence sets the foreground to black and the background to black. In ANSIPLUS, the current foreground is set to whatever the current background is, making text invisible on a potentially colored background. Okay but I can't get it to work right for me. If you come up with a cool prompt that can show this let me know here.
* Strikethrough : The table shows what it is suppose to do. I have not been able to get the effect to work. Let me know if you are able to here.
* Bold off: Turns off bold if you don't want it to go through your whole prompt.
* Italics off: This turns off italics so it doesn't go through your whole prompt.
* Underline off: Turns off the underline feature so it doesn't go through your whole prompt.
* Blink off: Turns off the blink feature so your whole prompt doesn't blink.
Inverse off: Turns off inverse colors so your whole prompt isn't reversed.
* Strikethrough off: Ends the strikethrough line so your whole prompt doesn't have a line through it. At least that is the idea Hell I couldn't get the line in the first place.


You will probably note there are a lot of numbers not in the chart. I did to. I started looking around and found out why. They won't work in a prompt. ANSI hasn't even set up all of the missing numbers with features yet and some of those missing numbers are for really advanced features that will serve absolutely no purpose here. Also there are a couple of features like shadow that just don't do a damn thing. I will list all of the pages of stuff I went through for this and if you can make a prompt work with it and keep it simple I will add it. Educate me here.

The Bourne Shell:

The Bourne shell does support colors. But it isn't easy. You have to use the vi editor to make it work. Since giving a vi tutorial is almost a subject on it's own I will not go into a lot of detail here on how to use vi. Understand vi stands for very intimidating editor. But you can't get the symbols you want in the way they need to be to work. I am a newbie and love ee. It is as it's name describes a Easy Editor. Now on to adding colors to your prompt. To color your prompt you will need to place this symbol in your prompt ^[[Xm Replace X with the number of the color you want. Now before I go to the example a few things about why this is a pain in the ass. ^[ Those symbols are made by going into vi and editing and typing ctrl +v ( pressed at the same time) and then pressing the Esc button. You will note another [ after the first one you get that by pressing the key above the ' key (qwerty style keyboard). So the keying is very weird. And having to be forced to do it in vi is like being lead through The Twilight Zone. Oh yeah doing a copy/ paste doesn't work either. At least for the multiple times I tried it.Now for the example:


PS1="^[[31m`whoami`@:`hostname | sed 's/\..*//'`^[[0m>" # Custom prompt settings

PS1="red text whoami @ hostname normal display> So basically you have told the computer all text from here to be red. After that you have told the computer to place the hostname and whoami in the prompt. Now return the display to a normal setting. This is important because forgetting to tell it to go back to normal means everything will be red, or worse whatever your last color command is. The point being when you are done make sure you tell it to return to normal.
Okay more than one color:

PS1="^[[31m`whoami`@^[[1;31m:`hostname | sed 's/\..*//'`^[[0m>" #Custom Prompt settings

PS1 = "red text whoami yellow text hostname normal display>

Okay background color:

PS1="^[[46;31m`whoami`@^[[1;31m:`hostname | sed 's/\..*//'`^[[0m>" #Custom Prompt settings

PS1 ="Cyan background red text whoami yellow text hostname normal display>" You can have multiple colors in the brackets. Separate them with a semicolon. Also don't ask for two colors to cover the same text. Your computer will get mad at you.

Certain colors need a semicolon in order to appear. Yellow as the above example shows is 1;33 do not use just 33 or it will come out brown. If you have a 0;31 you don't need to place the 0.
These are just some of things you can do. Don't be afraid to experiment. Post your Bourne shell prompt here.
Also there is the issue of tput but it is also very new to me and I haven't used it. But I have had people make the suggestion of using that. Hey if it works for you go for it.

The Korn Shell:

The Korn shell does support colors. To color the prompt you will want to place this symbol in your prompt.$'\E[Xm'. Replace X with the number of the color you want. Example:

PS1=$'\E[31m'`logname`@`hostname -s`:$'\E[0m>' #Custom prompt settings.

PS1 = "red text whoami hostname normal display>"

So basically you have told the computer all text from here to be red. After that you have told the computer to place the hostname and whoami in the prompt. Now return the display to a normal setting. This is important because forgetting to tell it to go back to normal means everything will be red, or worse whatever your last color command is. The point being when you are done make sure you tell it to return to normal.
Okay more than one color:

PS1=$'\E[31m'`logname`@$'\E[1;33m'`hostname -s`:$'\E[0m>' #Custom prompt settings

PS1 = "red text whoami yellow text hostname normal display>

Okay background color:

PS1=$'\E[46;31m'`logname`@$'\E[1;33m'`hostname -s`:$'\E[0m>' #Custom prompt settings

PS1 ="Cyan background red text whoami yellow text hostname normal display>" You can have multiple colors in the brackets. Separate them with a semicolon. Also don't ask for two colors to cover the same text. Your computer will get mad at you.

Certain colors need a semicolon in order to appear. Yellow as the above example shows is 1;33 do not use just 33 or it will come out brown. If you have a 0;31 you don't need to place the 0.
These are just some of things you can do. Don't be afraid to experiment. Post your Korn shell prompt here.

BASH:

Bash does support colors in the prompt. If you used the prompt I showed earlier you know that. Now how you can do it. Place this symbol in front of the section you want to colonize. \[\033[Xm\]. Replace the "X" with the number of the color you want.Example:

PS1="\[\033[31m\][\u@\h]\[\033[0m\]>"

The translation the computer does is this:
PS1="red text begin[whoami@hostname]normal display>

So basically you have told the computer all text from here to be red. After that you have told the computer to place the username and hostname in the prompt. Now return the display to a normal setting. This is important because forgetting to tell it to go back to normal means everything will be red, or worse whatever your last color command is. The point being when you are done make sure you tell it to return to normal.
Okay more than one color:

PS1="\[\033[31m\][\u@\[\033[1;33m\]\h]\]\033[0m\]>"

PS1="red text[whoami@ yellow text hostname] normal display>

Okay background color:

PS1="\[\033[46;31m\][\u@\[\033[1;33m\]\h]\]\033[0m\]>"

PS1="Cyan background red text [whoami@ yellow text hostname] normal display> You can have multiple colors in the brackets. Separate them with a semicolon. Also don't ask for two colors to cover the same text. Your computer will get mad at you.

Certain colors need a semicolon in order to appear. Yellow as the above example shows is 1;33 do not use just 33 or it will come out brown. If you have a 0;31 you don't need to place the 0.

These are just some of things you can do. Don't be afraid to experiment. Post your BASH prompt here.

Z Shell:

The Z shell does support colors.To color the prompt you will want to do place this symbol in your prompt. %{\e[Xm%} Replace X with the number you want for the color you want.Example:

PROMPT=$'%{\e[0;31m%}%m %n %{\e[0m%}$'

PROMPT= red text hostname whoami normal display

So basically you have told the computer all text from here to be red. After that you have told the computer to place the whoami and hostname in the prompt. Now return the display to a normal setting. This is important because forgetting to tell it to go back to normal means everything will be red, or worse whatever your last color command is. The point being when you are done make sure you tell it to return to normal.
Okay more than one color:

PROMPT=$'%{\e[0;31m%}%m %{\e[1;33m%}%n %{\e[0m%}$'

PROMPT="red text hostname yellow text whoami normal display>

Okay background color:

PROMPT=$'%{\e[0;46;31m%}%m %{\e[1;33m%}%n %{\e[0m%}$'

PROMPT="Cyan background red text hostname yellow text whoami normal display$" You can have multiple colors in the brackets. Separate them with a semicolon. Also don't ask for two colors to cover the same text. Your computer will get mad at you.

With the Z shell you must include all 0's or 1's in your brackets however you only need to do it once. As in %{\e[0;46;31m%}. Don't be afraid to experiment. Post your Z shell here.

*Addendum to Z Shell Color Prompt*

If the above example does not work for you, you can try it this way. It is a bit more complicated but should work. Add this to your .zshrc:

#Prompt Color Table Z shell
fg_black=$'\e[0;30m'
fg_red=$'\e[0;31m'
fg_green=$'\e[0;32m'
fg_brown=$'\e[0;33m'
fg_blue=$'\e[0;34m'
fg_purple=$'\e[0;35m'
fg_cyan=$'\e[0;36m'
fg_lgray=$'\e[0;37m'
fg_dgray=$'\e[1;30m'
fg_lred=$'\e[1;31m'
fg_lgreen=$'\e[1;32m'
fg_yellow=$'\e[1;33m'
fg_lblue=$'\e[1;34m'
fg_pink=$'\e[1;35m'
fg_lcyan=$'\e[1;36m'
fg_white=$'\e[1;37m'
#Text Background Colors
bg_red=$'\e[0;41m'
bg_green=$'\e[0;42m'
bg_brown=$'\e[0;43m'
bg_blue=$'\e[0;44m'
bg_purple=$'\e[0;45m'
bg_cyan=$'\e[0;46m'
bg_gray=$'\e[0;47m'
#Attributes
at_normal=$'\e[0m'
at_bold=$'\e[1m'
at_italics=$'\e[3m'
at_underl=$'\e[4m'
at_blink=$'\e[5m'
at_outline=$'\e[6m'
at_reverse=$'\e[7m'
at_nondisp=$'\e[8m'
at_strike=$'\e[9m'
at_boldoff=$'\e[22m'
at_italicsoff=$'\e[23m'
at_underloff=$'\e[24m'
at_blinkoff=$'\e[25m'
at_reverseoff=$'\e[27m'
at_strikeoff=$'\e[29m'

To color the prompt you will want to do place the name in your prompt. ${X} Replace X with the name you want for the color you want.Example:

PS1="${fg_red}%m %n ${at_normal}$"

PS1= red text hostname whoami normal display

Two colors:

PS1="${fg_red}%m ${fg_yellow}%n ${at_normal}$"

PS1= red text hostname yellow text whoami normal display

Background color:

Well now you have issues. Things like:

PS1="${bg_cyan;fg_red}%m ${fg_yellow}%n ${at_normal}$" won't work properly.

What you have to do is create a line that mimics what you want. For example:

#Mixed Colors
mx_color0=$'\e[46;31m'
mx_color1=$'\e[46;1;33m
' PS1="${mx_color0}%M ${mx_color1}%n ${at_normal}$"
You would add those lines to your .zshrc. That would give you the:

PS1="Cyan background red text hostname yellow text whoami normal display$"

Now basically you can create those lines in any combo you want and call them anything you want. I just set them up like you see for an easy to understand setup. But you could do this:

fore_black=$'\e[0;30m'
black0=$'\e[0;30m'
darkness=$'\e[0;30m'

You get the idea as long as you put the name you created in the parenthesis and you don't make duplicates it can be called anything you want.

TC Shell:

The TC shell does support colors. To color the prompt you will want to place this symbol in your prompt.%{\033[Xm%}. Also right after your "set prompt = " you will want to place a \n if you don't the color prompts will not work.Example: set prompt = "\n%{\033[31m%}%m %n %{\033[0m%}>"

set prompt = "red text hostname whoami normal display>"

So basically you have told the computer all text from here to be red. After that you have told the computer to place the hostname and whoami in the prompt. Now return the display to a normal setting. This is important because forgetting to tell it to go back to normal means everything will be red, or worse whatever your last color command is. The point being when you are done make sure you tell it to return to normal.
Okay more than one color:

set prompt = "\n%{\033[31m%}%m %{\033[1;33m%}%n %{\033[0m%}>"

set prompt = "red text hostname yellow text whoami normal display>

Okay background color:

set prompt = "\n%{\033[46;31m%}%m %{\033[1;33m%}%n %{\033[0m%}>"

set prompt ="Cyan background red text hostname yellow text whoami normal display>" You can have multiple colors in the brackets. Separate them with a semicolon. Also don't ask for two colors to cover the same text. Your computer will get mad at you.

Certain colors need a semicolon in order to appear. Yellow as the above example shows is 1;33 do not use just 33 or it will come out brown. If you have a 0;31 you don't need to place the 0.
These are just some of things you can do. Don't be afraid to experiment. Post your TC shell prompt here.

*Addendum to TC Shell Color Prompt*

I have been pointed out another prompt variable that will also work in TC if the first one doesn't. %{^[[Xm%} replace X with the color code you want. You will have to go into the vi editor to create ^[ this is the ctrl+v keys then the Esc key. You can read more about it here

C Shell:

The C shell does support colors. To color the prompt you will want to place this symbol in your prompt.%{\033[Xm%}. Also right after your "set prompt = " you will want to place a \n if you don't the color prompts will not work.Example:

set prompt = "\n%{\033[31m%}%m %n %{\033[0m%}>"

set prompt = "red text hostname whoami normal display>"

So basically you have told the computer all text from here to be red. After that you have told the computer to place the hostname and whoami in the prompt. Now return the display to a normal setting. This is important because forgetting to tell it to go back to normal means everything will be red, or worse whatever your last color command is. The point being when you are done make sure you tell it to return to normal.
Okay more than one color:

set prompt = "\n%{\033[31m%}%m %{\033[1;33m%}%n %{\033[0m%}>"

set prompt = "red text hostname yellow text whoami normal display>

Okay background color:

set prompt = "\n%{\033[46;31m%}%m %{\033[1;33m%}%n %{\033[0m%}>"

set prompt ="Cyan background red text hostname yellow text whoami normal display>" You can have multiple colors in the brackets. Separate them with a semicolon. Also don't ask for two colors to cover the same text. Your computer will get mad at you.

Certain colors need a semicolon in order to appear. Yellow as the above example shows is 1;33 do not use just 33 or it will come out brown. If you have a 0;31 you don't need to place the 0.
These are just some of things you can do. Don't be afraid to experiment. Post your C shell prompt here.

The Lazy Shell Change

The interactive non login shell.

Changing you shell part 2.

So you don't want to have to log in under a different name to change your shell. Okay. you can do that. Just type in the name of the shell you want to. This part starts from you login shell.

Some notes that are important here. Korn and Bourne share some of the same files when you try to do a non login interactive shell request.To get it to read your .shrc or .kshrc file will depend on a few extra steps. It may seem scary at first. Don't worry you are not breaking anything and none of the changes are permanent.

Bourne Shell:

Okay you log into Bourne and you want to change to a:

Korn Shell: Place a .kshrc file in your home directory. Place your prompt value in that. Now edit your .shrc file and add these two lines at the bottom.

ENV=~/.kshrc # set up Korn shell option
export ENV

You should log out and back in the first time you do this.You shouldn't have to after the first time. Then at the prompt type:

ksh93

You will then have a interactive non login Korn shell. To exit out of it type:

exit

BASH: Place a .bashrc in your home directory and place your prompt settings in the .bashrc file. then at the prompt type:

bash

You will then have a interactive non login BASH shell. To exit out of it type:

exit

Z shell: Place a .zshrc in your home directory and place your prompt settings in the .zshrc file. then at the prompt type:

zsh

You will then have a interactive non login Z shell. To exit out of it type:

exit

TC/C Shell: Place a .tcshrc (.cshrc) in your home directory and place your prompt settings in the .tcshrc file. then at the prompt type:

tcsh or csh

You will then have a interactive non login TC/C shell. To exit out of it type:

exit

Now a small note FreeBSD does not separate the binaries for TC or C. If you place a .tcshrc file in your home directory it will always take precedence over a .cshrc file. Basically you can run a csh command for a prompt but what you are really doing is running TC with limited parameters.

Korn Shell:

Okay you log into Korn and you want to change to a:

Bourne Shell: Place a .shrc file in your home directory if you don't already have one. Place the prompt in the file as shown earlier in the document. It should already have a PS1 line in there just needed to be uncommented. At the prompt type this:

ENV=~/.shrc
Then the prompt will return and type this:

export ENV
Then the prompt will return and type this:

sh

You will then have a interactive non login Bourne shell. To exit out of it type:

exit

BASH: Place a .bashrc in your home directory and place your prompt settings in the .bashrc file. then at the prompt type:

bash

You will then have a interactive non login BASH shell. To exit out of it type:

exit

Z Shell: Place a .zshrc in your home directory and place your prompt settings in the .zshrc file. then at the prompt type:

zsh

You will then have a interactive non login Z shell. To exit out of it type:

exit

TC/C Shell: Place a .tcshrc (.cshrc) in your home directory and place your prompt settings in the .tcshrc file. then at the prompt type:

tcsh or csh

You will then have a interactive non login TC/C shell. To exit out of it type:

exit

Now a small note FreeBSD does not separate the binaries for TC or C. If you place a .tcshrc file in your home directory it will always take precedence over a .cshrc file. Basically you can run a csh command for a prompt but what you are really doing is running TC with limited parameters.

BASH:

Okay you log into BASH and you want to change to a:

Bourne Shell: Place a .shrc file in your home directory if you don't already have one. Place the prompt in the file as shown earlier in the document. It should already have a PS1 line in there just needed to be uncommented. At the prompt type this:

ENV=~/.shrc
Then the prompt will return and type this:

export ENV
Then the prompt will return and type this:

sh

You will then have a interactive non login Bourne shell. To exit out of it type:

exit

Korn Shell: Place a .kshrc in your home directory and place your prompt settings in the .kshrc file. then at the prompt type:

ENV=~/.kshrc
Then the prompt will return and type this:

export ENV
Then the prompt will return and type this:

ksh93

You will then have a interactive non login Korn shell. To exit out of it type:

exit

Z shell: Place a .zshrc in your home directory and place your prompt settings in the .zshrc file. then at the prompt type:

zsh

You will then have a interactive non login Z shell. To exit out of it type:

exit

TC/C Shell: Place a .tcshrc (.cshrc) in your home directory and place your prompt settings in the .tcshrc file. then at the prompt type:

tcsh or csh

You will then have a interactive non login TC/C shell. To exit out of it type:

exit

Now a small note FreeBSD does not separate the binaries for TC or C. If you place a .tcshrc file in your home directory it will always take precedence over a .cshrc file. Basically you can run a csh command for a prompt but what you are really doing is running TC with limited parameters.

Z Shell:

Okay you log into Z shell and you want to change to a:

Bourne Shell: Place a .shrc file in your home directory if you don't already have one. Place the prompt in the file as shown earlier in the document. It should already have a PS1 line in there just needed to be uncommented. At the prompt type this:

ENV=~/.shrc
Then the prompt will return and type this:

export ENV
Then the prompt will return and type this:

sh

You will then have a interactive non login Bourne shell. To exit out of it type:

exit

Korn Shell: Place a .kshrc in your home directory and place your prompt settings in the .kshrc file. then at the prompt type:

ENV=~/.kshrc
Then the prompt will return and type this:

export ENV
Then the prompt will return and type this:

ksh93

You will then have a interactive non login Korn shell. To exit out of it type:

exit

BASH: Place a .bashrc in your home directory and place your prompt settings in the .bashrc file. then at the prompt type:

bash

You will then have a interactive non login BASH shell. To exit out of it type:

exit

TC/C Shell: Place a .tcshrc (.cshrc) in your home directory and place your prompt settings in the .tcshrc file. then at the prompt type:

tcsh or csh

You will then have a interactive non login TC/C shell. To exit out of it type:

exit

TC Shell:

Okay you log into TC and you want to change to a:

Bourne Shell: Place a .shrc file in your home directory if you don't already have one. Place the prompt in the file as shown earlier in the document. It should already have a PS1 line in there just needed to be uncommented. At the prompt type this:

ENV=~/.shrc
Then the prompt will return and type this:

export ENV
Then the prompt will return and type this:

sh

You will then have a interactive non login Bourne shell. To exit out of it type:

exit

Korn Shell: Place a .kshrc in your home directory and place your prompt settings in the .kshrc file. then at the prompt type:

ENV=~/.kshrc
Then the prompt will return and type this:

export ENV
Then the prompt will return and type this:

ksh93

You will then have a interactive non login Korn shell. To exit out of it type:

exit

BASH:Place a .bashrc in your home directory and place your prompt settings in the .bashrc file. then at the prompt type:

bash

You will then have a interactive non login BASH shell. To exit out of it type:

exit

Z shell:Place a .zshrc in your home directory and place your prompt settings in the .zshrc file. then at the prompt type:

zsh

You will then have a interactive non login Z shell. To exit out of it type:

exit

C Shell: You really want to do this. Really. I don't know why but okay. at the prompt type:

csh

You will then be place in a illusionary C shell. TC and C shells both read the same binaries so it is always going to read the .tcshrc file. You are still working in a TC shell just with limited parameters.

C Shell:

Okay you log into C and you want to change to a:

Bourne Shell: Place a .shrc file in your home directory if you don't already have one. Place the prompt in the file as shown earlier in the document. It should already have a PS1 line in there just needed to be uncommented. At the prompt type this:

ENV=~/.shrc
Then the prompt will return and type this:

export ENV
Then the prompt will return and type this:

sh

You will then have a interactive non login Bourne shell. To exit out of it type:

exit

Korn Shell: Place a .kshrc in your home directory and place your prompt settings in the .kshrc file. then at the prompt type:

ENV=~/.kshrc
Then the prompt will return and type this:

export ENV
Then the prompt will return and type this:

ksh93

You will then have a interactive non login Korn shell. To exit out of it type:

exit

BASH:Place a .bashrc in your home directory and place your prompt settings in the .bashrc file. then at the prompt type:

bash

You will then have a interactive non login BASH shell. To exit out of it type:

exit

Z shell: Place a .zshrc in your home directory and place your prompt settings in the .zshrc file. then at the prompt type:

zsh

You will then have a interactive non login Z shell. To exit out of it type:

exit

TC Shell: Okay if you do this you can mess things up a little. If you have only a .cshrc file in your home directory that is what is read when you log in. However in order for you to have a TC shell you will need a .tcshrc file. The problem is once you put that in. You .csh is left in the dust. Every time you log in that is where it's reading, .tcshrc has precedence over .cshrc. Okay now for the really bad news. If all you have is a ,cshrc it doesn't really matter. The TC/C shell are basically the same binaries. C shell just is TC shell with few less functions. Kind of redundant isn't it.

The Lazy Prompt Change

Okay so you don't want to edit your files. Damn that is lazy. Or maybe you just need your prompt to be different for a little while. Well here you go.

Bourne Shell: Okay at your prompt type this:

PS1="-->"

This will change your prompt to look like this:

-->

You can always type another style of prompt for what ever floats your boat.

PS1="What is thy bidding Master?"

What is thy bidding Master?

The changes aren't permanent so if you log out and back in you will have your original prompt back. That's why you edit your files. Because a prompt placed in a file is what you system defaults to unless you change it at the prompt.

Korn: Okay at your prompt type this:

PS1="-->"

This will change your prompt to look like this:

-->

You can always type another style of prompt for what ever floats your boat.

PS1="What is thy bidding Master?"

What is thy bidding Master?

The changes aren't permanent so if you log out and back in you will have your original prompt back. That's why you edit your files. Because a prompt placed in a file is what you system defaults to unless you change it at the prompt.

BASH: Okay at your prompt type this:

PS1="-->"

This will change your prompt to look like this:

-->

You can always type another style of prompt for what ever floats your boat.

PS1="What is thy bidding Master?"

What is thy bidding Master?

The changes aren't permanent so if you log out and back in you will have your original prompt back. That's why you edit your files. Because a prompt placed in a file is what you system defaults to unless you change it at the prompt.

Z Shell:Okay at your prompt type this:

PROMPT="-->"

This will change your prompt to look like this:

-->

You can always type another style of prompt for what ever floats your boat.

PROMPT="What is thy bidding Master?"

What is thy bidding Master?

The changes aren't permanent so if you log out and back in you will have your original prompt back. That's why you edit your files. Because a prompt placed in a file is what you system defaults to unless you change it at the prompt.

TC/C Shell: Okay at your prompt type this:

set prompt="-->"

This will change your prompt to look like this:

-->

You can always type another style of prompt for what ever floats your boat.

set prompt="What is thy bidding Master?"

What is thy bidding Master?

The changes aren't permanent so if you log out and back in you will have your original prompt back. That's why you edit your files. Because a prompt placed in a file is what you system defaults to unless you change it at the prompt.

The Stuff Near the End

Well damn was that long enough. This the end of the article for now. And to think I originally wanted to look at including X term in it also. Well there definitely was a lot of work researching this puppy. I hope this help you customize your prompts. There were a lot of people and websites that helped me to bring this thing together. Here is that list.

Jason Neuman For putting up with my articles and not deleting them.
David Korn For actually replying to my emails with my novice level questions.
Net_Fish For letting me know that I could customize my prompt.
drdink For helping me even if it was like pulling teeth to get answers from him.
comp.unix.bsd.freebsd.misc for letting me post my ridiculous questions to their list. Some of them even got answered.
Special Thanks to the following Jens Schweikhardt, Kristoffer Persson,and jpd of the newsgroup who helped me with the Bourne Shell issue.
Basalisk in #tekniq for being really patient with me in trying to understand the responses I got on the Bourne shell issue.
Umberto Quaia (from the newsgroup)for helping me tackle the echo issue. Which ultimately I edited out because of it's complexity. And for helping me with a bunch of other questions that came up as I was working on this.Michal from comp.unix.bsd.freebsd.misc who helped with the addendums to Z and TC shell.

The list of websites that I found helpful in no particular order:

The ANSI Stuff:
http://www.bluesock.org/~willg/dev/ansi.html A little advanced for me but still helpful.
http://pueblo.sourceforge.net/doc/manual/ansi_color_codes.html Very nice with some good explanations about the Bold issue.
Kristofer Sweger has a great page on ANSI color codes and functions.
Joe Smith has the really technical stuff about ANSI buried deep in this page. It went way over my head.
The dircolors man page. Since I couldn't bring it up from my computer. From the Linuxgazette.

Some of the Prompts I came across:
The Bash Power User prompt So much of this went way beyond me.
Steve Parker This guy is smart. Here is his tutorial on the Bourne Shell.
About.com is a great tutorial website . To bad they have that lousy pop up. This page is about shell variables.
J. Yoon has the best site for custom prompt options. This is the page that inspired me.
kung-foo.tv had this thing buried deep in their website. It shows some of the TC colored prompt options.
Daemon News has a page of custom prompts. They are great examples of some very cool very overdone prompts.
IBM even got into the picture and the site has a really nice color graphic of the ANSI codes. Written by Daniel Robbins.
Dotfiles.com has a really nice page of prompts.
Jon C. LeBlanc wrote this article on Generic Unix Interactive Prompts.
Kuro5hin has a page here asking people for samples of their unique prompts.
Linuxlookup has a nice how to on BASH with the ANSI color chart.
Mac OS X Hints has a page for TC shell prompts.
BSDWiki has a page on custom shell prompts. Note this link no longer works. I don't know what happened to BSDWiki.
FreeBSD Diary has a page on the BASH prompt.
FreeBSD Diary has another page here on the TC shell prompt.
That is my list of some of the better webpages I came across. Please check them out. And if you have a comment or a suggestion or a prompt you want to shows do so here.

2007/10/27 02:14 2007/10/27 02:14