반응형

1.$TOMCAT/conf/tomcat-user.xml 파일 수정

 -역할(Role) 및 사용자 계정(user) 추가. 계정/패스워드는 원하는 값으로 설정하시면 됩니다.

<?xml version="1.0" encoding="UTF-8"?>
...
<!--
  <role rolename="tomcat"/>
  <role rolename="role1"/>
  <user username="tomcat" password="<must-be-changed>" roles="tomcat"/>
  <user username="both" password="<must-be-changed>" roles="tomcat,role1"/>
  <user username="role1" password="<must-be-changed>" roles="role1"/>
-->


<role rolename="manager-gui"/>
<user username="tomcat" password="password1!" roles="manager-gui"/>



</tomcat-users>

 

2.$TOMCAT/webapps/manager/META-INF/context.xml 수정

 -클라이언트 IP로 접속 가능하게 하려면 org.apache.catalina.valves.RemoteAddrValve 태그는 주석처리 합니다.

<?xml version="1.0" encoding="UTF-8"?>
...
<Context antiResourceLocking="false" privileged="true" >
<!--
  <Valve className="org.apache.catalina.valves.RemoteAddrValve"
         allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" />
-->

  <Manager sessionAttributeValueClassNameFilter="java\.lang\.(?:Boolean|Integer|Long|Number|String)|org\.apache\.catalina\.filters\.CsrfPreventionFilter\$LruCache(?:\$1)?|java\.util\.(?:Linked)?HashMap"/>
</Context> 

 

3.Tomcat 기동

$TOMCAT/bin/startup.sh

브라우저 접속(http://ip:8080/manager)

관리자 페이지접속 화면

 

1.standalone.conf JAVA_OPTS 변수 또는 start 스크립트에 아래 설정 추가

-Dlog4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator

 

2.module 설정

 ...modules/net/sf/log4jdbc/main/log4jdbc-log4j2-jdbc4-1.12.jar
 ...modules/net/sf/log4jdbc/main/module.xml

module.xml

<?xml version='1.0' encoding='UTF-8'?>
<module xmlns="urn:jboss:module:1.1" name="net.sf.log4jdbc">
    <resources>
        <resource-root path="log4jdbc-log4j2-jdbc4-1.12.jar"/>
    </resources>

    <dependencies>
        <module name="javax.api"/>
        <module name="javax.transaction.api"/>
        <module name="org.slf4j"/>
        <module name="com.h2database.h2"/>
        <module name="com.oracle"/>
        <module name="org.mariadb"/>
    </dependencies>
</module>

(com.oracle - Orlacle jdbc-dirver  / org.mariadb - mariadb driver)

 

3.standalone*.xml 설정

......
        <subsystem xmlns="urn:jboss:domain:datasources:5.0">
            <datasources>
                <datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
                    <connection-url>jdbc:log4jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
                    <driver>log4jdbc</driver>
                    <security>
                        <user-name>sa</user-name>
                        <password>sa</password>
                    </security>
                </datasource>
                <datasource jndi-name="java:/OracleDS" pool-name="OracleDS">
                    <connection-url>jdbc:log4jdbc:oracle:thin:@localhost:1521:orcalesid</connection-url>
                    <driver-class>oracle.jdbc.driver.OracleDriver</driver-class>
                    <driver>log4jdbc</driver>
                    <security>
                        <user-name>test</user-name>
                        <password>test</password>
                    </security>
                    <validation>
                        <valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.oracle.OracleValidConnectionChecker"/>
                        <background-validation>true</background-validation>
                        <stale-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.oracle.OracleStaleConnectionChecker"/>
                        <exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.oracle.OracleExceptionSorter"/>
                    </validation>
                </datasource>
                <datasource jndi-name="java:jboss/datasources/JpetStoreDS" pool-name="jpetstore">
                    <connection-url>jdbc:log4jdbc:mariadb://192.168.0.163:3306/jpetstore</connection-url>
                    <driver>log4jdbc</driver>
                    <security>
                        <user-name>test</user-name>
                        <password>test</password>
                    </security>
                </datasource>
                <drivers>
                    <driver name="h2" module="com.h2database.h2">
                        <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
                    </driver>
                    <driver name="oracle" module="com.oracle"/>
                    <driver name="mariadb" module="org.mariadb"/>
                    <driver name="log4jdbc" module="net.sf.log4jdbc"/>
                </drivers>
            </datasources>
        </subsystem> 

...... 

 

4.Connection 테스트

 -테스트 환경상 Oracle DB 접속은 불가능하여 Maria DB로 테스트 수행하였습니다.

[standalone@192.168.0.10:10990 /] data-source test-connection-in-pool --name=jpetstore
true
[standalone@ 192.168.0.10:10990 /] data-source test-connection-in-pool --name=ExampleDS
true 


로그화면

2019-11-08 16:25:25,502 INFO  [jdbc.connection] (management-handler-thread - 1) 1. Connection opened
2019-11-08 16:25:25,502 INFO  [jdbc.audit] (management-handler-thread - 1) 1. Connection.new Connection returned
2019-11-08 16:25:25,510 INFO  [jdbc.audit] (management-handler-thread - 1) 1. Connection.getTransactionIsolation() returned 4
2019-11-08 16:25:25,510 INFO  [jdbc.audit] (management-handler-thread - 1) 1. Connection.isReadOnly() returned false
2019-11-08 16:25:25,512 INFO  [jdbc.audit] (management-handler-thread - 1) 1. Connection.getMetaData() returned org.mariadb.jdbc.MariaDbDatabaseMetaData@54d3ea99
2019-11-08 16:25:25,512 INFO  [jdbc.audit] (management-handler-thread - 1) 1. Connection.getMetaData() returned org.mariadb.jdbc.MariaDbDatabaseMetaData@4eaeff49
2019-11-08 16:25:25,512 INFO  [jdbc.audit] (management-handler-thread - 1) 1. Connection.getMetaData() returned org.mariadb.jdbc.MariaDbDatabaseMetaData@42a42903
2019-11-08 16:25:37,122 INFO  [jdbc.connection] (management-handler-thread - 1) 2. Connection opened
2019-11-08 16:25:37,124 INFO  [jdbc.audit] (management-handler-thread - 1) 2. Connection.new Connection returned
2019-11-08 16:25:37,128 INFO  [jdbc.audit] (management-handler-thread - 1) 2. Connection.getTransactionIsolation() returned 2
2019-11-08 16:25:37,128 INFO  [jdbc.audit] (management-handler-thread - 1) 2. Connection.isReadOnly() returned false
2019-11-08 16:25:37,129 INFO  [jdbc.audit] (management-handler-thread - 1) 2. Connection.getMetaData() returned dbMeta0: conn0: url=jdbc:h2:mem:test user=SA
2019-11-08 16:25:37,129 INFO  [jdbc.audit] (management-handler-thread - 1) 2. Connection.getMetaData() returned dbMeta1: conn0: url=jdbc:h2:mem:test user=SA
2019-11-08 16:25:37,130 INFO  [jdbc.audit] (management-handler-thread - 1) 2. Connection.getMetaData() returned dbMeta2: conn0: url=jdbc:h2:mem:test user=SA 

jboss migration 프로그램 다운로드
 https://github.com/wildfly/wildfly-server-migration/releases

 

샘플 구성환경
-----------------------------------------------------------
Jboss 6.4 경로: /SW/jboss/jboss-eap-6.4
Jboss 7.2 경로: /SW/jboss/jboss-eap-7.2
-----------------------------------------------------------

메뉴얼 jboss-server-migration/docs/user-guide/index.html

 

1.jboss 7.2 설치

 /SW/jboss에 jboss-eap-7.2.5.zip 파일 업로드 (Jboss EAP 7.2에서 패치5가 적용된 파일)
 $ cd /SW/jboss
 $ unzip jboss-eap-7.2.5.zip

 

2.마이그레이션 툴 압축 해제 

/SW/jboss에 jboss-server-migration-1.7.0.Final.zip 파일 업로드
 $ unzip jboss-server-migration-1.7.0.Final.zip
 $ cd jboss-server-migration

 

3.마이그레이션 환경파일 수정

vi /SW/jboss/jboss-server-migration/configuration/environment.properties

####### SERVER PATHS
# Jboss EAP 6.4의 정보
server.source.standalone.serverDir=/SW/jboss/jboss-eap-6.4/standalone
server.source.standalone.configDir=/SW/jboss/jboss-eap-6.4/standalone/configuration
# 마이그레이션 환경파일 설정(모두 마이그레이션 할 경우: standalone.xml,standalone-full.xml,standalone-ha.xml,standalone-full-ha.xml)
server.source.standalone.configFiles=standalone.xml

# Jboss EAP 7.2 설치 경로
server.target.standalone.serverDir=/SW/jboss/jboss-eap-7.2/standalone
server.target.standalone.configDir=/SW/jboss/jboss-eap-7.2/standalone/configuration

# deployment 이관
deployments.migrate-deployments.skip=false
 
# 모듈 포함(jdbc 드라이버)
modules.includes=org.mariadb


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

####### SERVER PATHS

# Jboss EAP 6.4의 정보
server.source.standalone.serverDir=/SW/jboss/jboss-eap-6.4/standalone
server.source.standalone.configDir=/SW/jboss/jboss-eap-6.4/standalone/configuration
# 마이그레이션 환경파일 설정(모두 마이그레이션 할 경우: standalone.xml,standalone-full.xml,standalone-ha.xml,standalone-full-ha.xml)
server.source.standalone.configFiles=standalone.xml

# Jboss EAP 7.2 설치 경로
server.target.standalone.serverDir=/SW/jboss/jboss-eap-7.2/standalone
server.target.standalone.configDir=/SW/jboss/jboss-eap-7.2/standalone/configuration

# deployment 이관
deployments.migrate-deployments.skip=false
 
# 모듈 포함(jdbc 드라이버)
modules.includes=org.mariadb

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

 

4.마이그레이션 수행

$ ./jboss-server-migration.sh -e /SW/jboss/jboss-server-migration/configuration/environment.properties -s /SW/jboss/jboss-eap-6.4 -t /SW/jboss/jboss-eap-7.2
----------------------------------------------------------
----  JBoss Server Migration Tool  -----------------------
----------------------------------------------------------Retrieving servers...
 INFO  SOURCE server name: EAP, version: 6.4.0.GA.
 INFO  TARGET server name: JBoss EAP, version: 7.2.5.GA.----------------------------------------------------------
----------------------------------------------------------Server migration starting... INFO  --- Migrating modules requested by environment... INFO  Module org.mariadb:main migrated.Migrate the source's standalone server?
yes/no? yes INFO  --- Migrating standalone server... INFO  No source's standalone content found to migrate. INFO  Source's standalone configurations found: [standalone.xml]Migrate all configurations?
yes/no? yes INFO  Migrating standalone configuration standalone.xml...
 INFO  Unsupported extensions removed: [org.jboss.as.threads]
 INFO  Unsupported subsystems removed: [urn:jboss:domain:threads:1.1]
 INFO  Module com.mariadb:main migrated.
 INFO  Subsystem elytron added.
 INFO  Subsystem web migrated.
 INFO  Subsystem undertow updated.
 INFO  Subsystem infinispan updated.
 INFO  Subsystem ee updated.
 INFO  Subsystem ejb3 updated.
 INFO  Subsystem remoting updated.
 INFO  Subsystem batch-jberet added.
 INFO  Subsystem core-management added.
 INFO  Subsystem request-controller added.
 INFO  Subsystem security-manager added.
 INFO  Subsystem singleton added.
 INFO  Subsystem discovery added.
 INFO  Subsystem ee-security added.
 INFO  Subsystem microprofile-config-smallrye added.
 INFO  Subsystem microprofile-health-smallrye added.
 INFO  Subsystem microprofile-opentracing-smallrye added.
 INFO  HTTP Upgrade Management configured.
 INFO  Socket binding's port expressions added.
 INFO  Security realms migrated.
 INFO  Security realm ApplicationRealm SSL server identity configured.
 INFO  Persistent deployments found: [test_page.war]This tool is not able to assert if persistent deployments found are compatible with the target server, skip persistent deployments migration?
yes/no? no
 INFO  Persistent deployment test_page.war migrated.Migrate the source's managed domain?
yes/no? noServer migration done. INFO
-------------------------------------------------------------------------------------------
 Task Summary
------------------------------------------------------------------------------------------- server ........................................................................... SUCCESS
  modules.migrate-modules-requested-by-user ....................................... SUCCESS
   modules.migrate-modules-requested-by-user.migrate-module(id=org.mariadb:main) .. SUCCESS
  standalone ...................................................................... SUCCESS
   standalone-configurations ...................................................... SUCCESS
    standalone-configuration(source=standalone.xml) ............................... SUCCESS-------------------------------------------------------------------------------------------
 Migration Result: SUCCESS
-------------------------------------------------------------------------------------------

 

5.jboss-eap 6.4의 실행/종료 스크립트 jboss-eap 7.2로 복사 후 환경에 맞게 수정

 

6.Jboss-eap 7.2 기동 및 서비스 점검

Docker는 애플리케이션을 "컨테이너"라는 독립된 환경에서 실행할 수 있도록 해주는 "컨테이너화 플랫폼"입니다. Docker는 애플리케이션과 필요한 라이브러리, 종속성을 하나의 이미지로 묶어 배포하므로, 개발 환경과 운영 환경 간의 차이로 발생하는 문제를 줄여주며 일관된 환경에서 애플리케이션을 실행할 수 있게 해줍니다.


Docker의 개념

- 컨테이너: 애플리케이션과 그 실행에 필요한 모든 요소를 포함하는 독립적인 실행 환경입니다. 컨테이너는 가상 머신(VM)과 달리 운영 체제를 공유하여 가볍고 빠르게 실행됩니다.
- 이미지: 컨테이너의 원본 파일 시스템입니다. 이미지는 코드, 런타임, 라이브러리 등 컨테이너 실행에 필요한 모든 요소를 포함하며, 이를 기반으로 여러 컨테이너를 생성할 수 있습니다.
- Docker Hub: Docker 이미지 저장소로, 다양한 이미지들을 다운로드하여 사용할 수 있습니다.

 

Docker의 활용

1. 개발 환경 설정: Docker를 이용해 특정 버전의 개발 환경을 쉽게 설정하고 공유할 수 있습니다.
2. 애플리케이션 배포: 일관된 환경을 제공하므로 개발에서 테스트, 운영까지 같은 이미지를 사용해 손쉽게 배포할 수 있습니다.
3. 마이크로서비스: 각 서비스가 독립된 컨테이너에서 실행되도록 구성해, 마이크로서비스 아키텍처를 효과적으로 구현할 수 있습니다.
4. 지속적 통합 및 배포(CI/CD): Docker는 자동화된 테스트와 배포 파이프라인에서 일관된 환경을 제공하여 신속한 CI/CD 구현을 지원합니다.

Docker는 개발과 배포의 일관성을 유지하고, 경량화된 컨테이너 환경을 통해 서버 자원을 효율적으로 사용할 수 있게 하여, 개발자와 운영팀의 생산성을 높여줍니다.

 

이미지 관리

 

이미지 검색하기
sudo docker search centos

이미지를 다운로드
sudo docker pull centos:latest

이미지 목록 출력
sudo docker images

이미지 삭제
sudo docker rmi ubuntu:latest

 

 

컨테이너 관리

컨테이너 생성하기
sudo docker run -i -t --name hello ubuntu /bin/bash
 > -i(interactive), -t(Pseudo-tty) 옵션을 사용하면 실행된 Bash 셸에 입력 및 출력을 할 수 있습니다.
 > --name 옵션으로 컨테이너의 이름을 지정할 수 있습니다. 이름을 지정하지 않으면 Docker가 자동으로 이름을 생성하여 지정합니다


컨테이너 시작
sudo docker start hello

컨테이너 종료
sudo docker stop hello

컨테이너 재시작
sudo docker restart hello

컨테이너 접속
sudo docker attach hello

컨테이너 안의 명령 실행
sudo docker exec hello echo "Hello World"

실행된 컨테이너 목록을 출력
sudo docker ps

전체 컨테이너 목록을 출력
sudo docker ps -a

컨테이너 삭제
sudo docker rm hello

 

 

데이터베이스 구성 예시

 

mysql 구성

 -컨테이너 생성
 $ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag

-새로운 컨테이너를 시작하고 원래  mysql 컨테이너에 대해  mysql 명령을 실행
 $ docker run -it --netwo성rk some-network --rm mysql mysql -hsome-mysql -uexample-user -p

-이 이미지는 Docker가 아닌 또는 원격 인스턴스의 클라이언트로도 사용할 수 있습니다.
 $ docker run -it --rm mysql mysql -hsome.mysql.host -usome-mysql-user -p

Mysql 컨테이너에 root계정의 bash로 접속
$ docker exec -it -u root mysql-5.7 bash


Oracle 11g 구성

Oracle 11g 다운로드
 $ docker pull jaspeen/oracle-xe-11g

Oracle 11g 컨테이너 생성
 $ docker run --name oracle11c -d -p 1521:1521 jaspeen/oracle-xe-11g

oracle 11g 실행하기 
docker exec -it oracle11g sqlplus

계정: system  암호: oracle


Dockerfile 작성

FROM ubuntu:14.04
MAINTAINER Foo Bar <foo@bar.com></foo@bar.com>

RUN apt-get update
RUN apt-get install -y nginx
RUN echo "\ndaemon off;" >> /etc/nginx/nginx.conf
RUN chown -R www-data:www-data /var/lib/nginx

VOLUME ["/data", "/etc/nginx/site-enabled", "/var/log/nginx"]

WORKDIR /etc/nginx

CMD ["nginx"]

EXPOSE 80
EXPOSE 443


-FROM: 어떤 이미지를 기반으로 할지 설정합니다. Docker 이미지는 기존에 만들어진 이미지를 기반으로 생성합니다. <이미지 이름>:<태그> 형식으로 설정합니다.
-MAINTAINER: 메인테이너 정보입니다.
-RUN: 셸 스크립트 혹은 명령을 실행합니다.  
 > 이미지 생성 중에는 사용자 입력을 받을 수 없으므로 apt-get install 명령에서 -y 옵션을 사용합니다(yum install도 동일).
 > 나머지는 nginx 설정입니다.
 > VOLUME: 호스트와 공유할 디렉터리 목록입니다. docker run 명령에서 -v 옵션으로 설정할 수 있습니다.
   예) -v /root/data:/data는 호스트의 /root/data 디렉터리를 Docker 컨테이너의 /data 디렉터리에 연결합니다.
-CMD: 컨테이너가 시작되었을 때 실행할 실행 파일 또는 셸 스크립트입니다.
-WORKDIR: CMD에서 설정한 실행 파일이 실행될 디렉터리입니다.
-EXPOSE: 호스트와 연결할 포트 번호입니다.

 

Dockerfile 설명(Jboss)

# jboss/base-jdk:8 이미지를 기본으로 한다.
FROM jboss/base-jdk:8
 
# local directory에 있는 wildfly-12.0.0.Final.tar.gz를 생성되는 Docker Image 내부의 /opt 로 복사 및 압축을 해제한다.
# local directory에 있는 파일의 경로는 해당 Dockerfile의 상대경로를 작성해야 한다.
ADD ./wildfly-12.0.0.Final.tar.gz /opt
 
# 생성되는 Docker Image의 환경변수를 지정한다.
ENV WILDFLY_VERSION 12.0.0.Final
ENV JBOSS_HOME /was/wildfly-$WILDFLY_VERSION
 
# 생성되는 Docker Image의 User를 root로 변경한다.
USER root
 
# 환경변수로 지정한 JBOSS_HOME Directory의 파일 소유자, 권한을 변경한다.
# 예제에서는 jboss 사용자에게 JBOSS_HOME Directory를 접근할 수 있는 권한을 주고 있음.
RUN chown -R jboss:0 ${JBOSS_HOME} \
    && chmod -R g+rw ${JBOSS_HOME}
 
# 환경변수 지정(Wildfly를 background에서 동작하게 한다.)
# 해당 옵션을 지정하지 않으면 컨테이너를 종료시킬 때 강제로 종료(sudo docker kill {containerID})시켜야 한다.
ENV LAUNCH_JBOSS_IN_BACKGROUND true
 
# 현재 사용자를 root에서 jboss로 변경한다.
USER jboss
 
# 컨테이너가 실행되었을 때 요청을 기다리고 있는 포트를 지정한다.
EXPOSE 8080
 
# 컨테이너가 실행되었을 때 실행되는 명령어를 정의한다.
# 예제에서는 standalone로 wildfly를 실행하고 모든 ip address에 bind를 하는 옵션을 주고 있다.(ip지정시 해당 ip만 접속이 허용됨)
CMD ["/was/wildfly-12.0.0.Final/bin/standalone.sh", "-b", "0.0.0.0"]


이미지 생성 및 파일 이동

이미지 생성(Dockerfile)
sudo docker build --tag hello:0.1 .

이미지 히스토리 조회
sudo docker history hello:0.1

컨테이너의 파일 꺼내기
sudo docker cp hello-nginx:/etc/nginx/nginx.conf ./

컨테이너의 변경사항을 이미지로 생성
sudo docker commit -; "Foo Bar <foo@bar.com>" -m "add hello.txt" hello-nginx hello:0.2

컨테이너에서 변경된 파일 확인
sudo docker diff hello-nginx

이미지,컨테이너 세부 정보 출력
sudo docker inspect hello-nginx

서버를 운영하다보면 다양한 IP로 부터 공격을 받게 됩니다.

접속 로그를 확인해보면 하루에도 수십번에 접속 시도를 확인 할 수 있습니다.

 

fail2ban 패키지를 사용하면 로그인 실패 횟수를 설정하고 해당 IP를 차단 할 수 있습니다.

1. fail2ban 설치

sudo dnf install fail2ban -y

 

2. SSH 감시를 위한 기본 설정

fail2ban의 기본 설정 파일을 편집하여 SSH 접속 실패에 대한 감시를 설정합니다.

 jail.local 파일이 없을 경우 jail.conf 파일을 jail.local로 복사하여 수정합니다.

sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
 

3. jail.local 설정

jail.local 파일에서 SSH 관련 설정을 추가합니다. 아래와 같이 설정할 수 있습니다.

[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/secure
maxretry = 5
bantime = 3600
findtime = 600
  • enabled = true: 해당 jail을 활성화합니다.
  • port = ssh: 감시할 포트를 지정합니다.
  • filter = sshd: SSH 접속 실패 패턴을 찾기 위한 필터를 지정합니다.
  • logpath = /var/log/secure: SSH 로그 파일 경로를 지정합니다.
  • maxretry = 5: 5번 실패 시 IP를 차단합니다.
  • bantime = 3600: 차단 시간(초)을 설정합니다. 여기서는 1시간(3600초)입니다.
  • findtime = 600: 10분(600초) 동안 5번 실패하면 차단합니다.

 

4. fail2ban 서비스 시작 및 재시작

설정을 마친 후 fail2ban 서비스를 시작하고 활성화합니다.

sudo systemctl start fail2ban
sudo systemctl 
enable fail2ban
 

5. 설정 확인

fail2ban이 올바르게 작동하는지 확인하려면 다음 명령어를 사용할 수 있습니다.

# 설정 상태 확인
sudo fail2ban-client status

# 차단된 IP 확인
sudo fail2ban-client status sshd
 

※ 명령어 수행 화면

[break_in@Linux /home/break_in]#  sudo fail2ban-client status
Status
|- Number of jail:      1
`- Jail list:   sshd
 
실제로 많은 IP가 차단되었음을 확인할 수 있습니다.
[break_in@Linux /home/break_in]#  sudo fail2ban-client status sshd
Status for the jail: sshd
|- Filter
|  |- Currently failed: 0
|  |- Total failed:     16
|  `- Journal matches:  _SYSTEMD_UNIT=sshd.service + _COMM=sshd
`- Actions
   |- Currently banned: 193
   |- Total banned:     194
   `- Banned IP list:   101.126.64.15 101.126.69.203 101.126.95.220 101.32.114.105 101.42.237.107 101.43.26.143 101.43.39.17 101.43.4.185 103.139.193.99 103.142.87.231 103.143.231.132 103.143.72.165 103.163.118.84 103.172.204.55 103.174.103.90 103.176.78.193 103.211.217.182 103.248.60.70 103.25.47.94 103.92.24.242 103.99.115.26 106.12.222.76 106.124.137.140 106.58.219.160 109.236.47.90 109.75.33.121 112.103.254.249 112.184.135.67 112.6.122.181 113.137.40.250 113.88.210.159 114.100.49.20 114.217.20.159 115.247.46.122 118.179.135.65 119.28.118.4 120.28.109.188 121.229.62.94 122.227.174.98 124.156.205.16 125.124.45.195 125.91.122.29 128.199.137.110 128.199.206.26 128.199.70.247 129.226.198.6 129.226.215.132 134.122.13.225 134.209.157.237 139.59.36.213 139.59.79.179 14.29.147.56 14.48.202.73 14.56.193.140 140.246.22.189 143.110.220.40 146.190.119.107 150.158.31.194 154.221.21.206 156.236.71.21 156.54.108.185 157.148.123.74 159.203.104.187 161.35.182.145 162.241.71.207 165.227.2.252 165.227.201.152 167.99.224.42 174.160.133.10 175.178.114.15 175.204.112.213 176.31.253.67 178.128.56.162 178.128.73.254 178.62.66.67 182.253.47.126 183.106.6.202 183.162.79.39 185.126.34.211 185.174.136.146 185.233.37.14 185.6.105.150 186.31.95.163 187.188.0.71 187.210.77.100 187.49.152.10 187.72.83.169 187.95.160.53 188.166.161.55 188.213.197.78 190.119.66.238 190.221.7.146 193.32.162.29 194.110.54.141 194.113.236.217 194.145.208.178 195.24.56.135 196.219.43.154 197.199.224.52 197.227.8.186 198.23.174.113 201.149.49.146 201.251.51.218 201.6.100.191 202.157.184.3 203.0.104.170 203.150.34.32 206.189.121.27 206.189.175.87 206.189.230.76 211.75.19.210 212.233.136.201 213.194.140.33 217.160.88.147 217.182.73.127 217.60.244.8 218.70.106.202 220.194.171.236 23.158.56.100 34.139.17.74 34.92.176.182 35.219.62.194 36.138.68.207 36.64.217.27 41.223.66.252 42.123.122.175 42.180.160.78 42.51.33.212 43.128.142.238 43.128.233.205 43.133.42.162 43.134.129.4 43.134.13.231 43.134.226.192 43.134.237.227 43.134.41.24 43.135.172.65 43.153.171.66 43.153.219.239 43.153.84.164 43.154.96.206 43.156.156.39 43.156.3.145 43.159.59.118 45.131.108.155 46.101.9.148 47.237.30.245 47.245.87.100 49.205.174.180 49.232.6.67 51.15.218.133 51.178.182.201 52.86.173.91 58.220.39.220 58.228.29.87 59.127.158.223 59.36.75.227 61.155.106.101 61.191.103.17 64.227.126.250 64.227.149.214 67.205.160.228 69.49.246.102 79.110.62.145 79.137.197.11 79.224.101.219 8.218.134.133 8.219.117.148 8.219.237.64 8.222.197.223 80.94.92.139 81.161.238.51 81.192.46.38 82.67.7.178 83.12.113.122 83.97.73.40 88.214.25.16 89.185.85.182 89.46.223.31 89.46.223.35 91.196.54.125 91.205.219.185 91.237.163.37 91.92.252.162 92.87.22.210 93.113.63.124 93.197.94.25 94.228.169.65 95.181.86.2 95.214.27.253 95.90.242.212 96.126.113.215 8.222.172.160

 

6. 차단된 IP 해제 방법

SSH 접속 간 패스워드 입력 실수로 인해 내 PC IP가 차단될 경우의 조치 방법입니다.

sudo fail2ban-client set sshd unbanip 192.168.0.100

'IT기술노트 > Linux' 카테고리의 다른 글

Linux Bash 쉘 프로그래밍  (4) 2024.10.31

 

신입사원으로 입사했을 때 실습하고 정리했던 내용입니다^^
실무에서 많이 사용하는 부분이니 참고하시기 바랍니다~
 
-read 명령: 빌트인 명령으로써 터미널 또는 파일로부터 입력 문자열을 읽을 때 사용한다.
 

 

<read 명령어 옵션>
read 명령 옵션
의미
read answer
표준 입력으로부터 한 라인을 읽고 읽은 내용을 answer 변수의 값으로 할당
read first last
표준 입력으로부터 한 라인을 읽는데, 공백 또는 newline을 기준으로 첫 번째 단어는 first 변수의 값으로, 나머지 단어는 last 변수의 값으로 할당
read
표준 입력으로부터 한 라인을 읽고 REPLY 빌트인 변수의 값으로 할당
read –a arrayname
arrayname으로 명명된 배열의 단어 목록을 읽음
read –e
대화형 쉘에서 사용
read –p prompt
prompt를 출력하고, 입력을 기다리고, 입력 내용을 REPLY 변수에 저장
read –r line
백슬래시(\)를 포함하는 입력을 허용
 
# vi qeustion.sh
----------------------------------------------------------------------------
#!/bin/bash
# 스크립트명 : qeustion.sh
 
echo -e "행복하세요? : \c"
read answer
echo "$answer 라고 대답하셨네요 "
echo -e "이름이 어떻게 되세요? : \c"
read last first
echo "안녕하세요 $last $first 님"
echo -n "어디사세요? : "
read
echo $REPLY !
read -p "사용하는 리눅스 배포판은 무엇인가요? : "
echo $REPLY !
echo -n " 대표적인 3가지 리눅스는? : "
read -a dist
echo "${dist[2]}를 세 번째로 적어주셨네요"
----------------------------------------------------------------------------
# chmod +x qeustion.sh
# ./question.sh
 
산술 연산
 
1. 정수형 산술 연산
-declare 명령: 정수형 변수를 선언하는 명령
# declare -i -> 정수형으로 선언된 변수의 목록과 값을 출력
 
# declare -i num
# num=hello
# echo $num
# num=10+10
# num="10 + 10"  -> 띄어쓰기 사용시 " " 필히 사용
# echo $num
 
-진수 표기와 사용(10진수,2진수,8진수,16진수)
<형식>
변수명=진수#숫자
n=2#101  -> 2진수 101을 n에 할당
# declare -i x=016  -> 10진수 16을 선언
# echo $x  -> 출력값: 14
# declare x=2#011  -> 2진수 011 선언
# echo $x -> 출력값: 3
# declare x=8#13  -> 8진수 13을 선언
# echo $x  -> 출력값: 11
 
-let 명령: 빌트인 명령으로 정수형 산술 연산을 수행하고 숫자 표현식을 테스트한다.
# i=10
# let i=i+10
# echo $i
# let "i+=5"
# echo $1
 
2. 실수형 산술 연산: bash는 정수형 연산만 지원한다. 하지만, bc, awk 명령을 사용하면 더욱 복잡한 계산을 할 수 있다.
# n=`echo "scale=2; 20 / 3" | bc`  -> 즉 소수점 아래 2자리(scale)로 지정하고 20을 3으로 나누고 결과값을 bc아규먼트에 전달
# echo $n  -> 출력값: 6.66
# m=`awk -v x=2.66 -v y=5.22 'BEGIN{printf "%.2f\n", x*y}' `
 -> x와 y변수의 값을 할당하고 awk를 사용하여 x와 y를 곱한 값에서 소수점 2자리까지 출력
# echo $m  -> 출력값: 13.89
 ※ bc 명령은 대화형으로 문장을 실행하는 무한 정확도의 숫자를 지원하는 언어이다.
 
위치 파라미터와 명령라인 아규먼트
-위치 파라미터
<위치 파라미터 변수>
위치 파라미터 변수
의미
$0
실행한 스크립트 이름을 할당
$#
위치 파라미터의 개수의 값을 가짐
$*
위치 파라미터들의 모든 목록을 가짐
$@
큰따옴표로 감싸졌을 경우를 제외하고 $*와 같은 의미임
“$*”
단일 아규먼트로 확장
예) “$1 $2 $3”
“$@”
아규먼트를 분리하여 확장
  예) “$1” “$2” “$3”
$1 … ${10}
위치 파라미터들을 개별적으로 참조
 
vi hello.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
echo $0 을 호출하였음.
echo 첫 번째 : $1 , 두 번째 : $2 , 세 번째 : $3
echo 위치 파라미터 개수 : $#
----------------------------------------------------------------------------------
# chmod +x hello.sh
# ./hello.sh  
 
# ./hello.sh 홍길동 장길산 김정호
 
-set 명령과 위치 파라미터
# set--  -> 모든 파라미터 재설정, $0  -> 스크립트 이름
 
# vi args.sh
----------------------------------------------------------------------------------
#!/bin/bash
# 스크립트명 : args.sh
# 명령라인 아규먼트 테스트
 
echo 스크립트명 : $0
echo 전체 아규먼트 : $*
echo 첫 번째 아규먼트 : $1
echo 두 번째 아규먼트 : $2
echo 전체 아규먼트 수 : $#
oldargs=$*
set CentOS Fefora Ubuntu # 위치 파라미터 재설정
echo 전체 파라미터 : $*
echo 전체 위치 파라미터 수 $#
echo "첫 번째 위치 파라미터 : $1"
set $(date) # 위치 파라미터 재설정
echo 오늘은 $2 $3 $1
echo "\$oldargs : $oldargs"
set $oldargs
echo $1 $2 $3
----------------------------------------------------------------------------------
# chmod +x args.sh
# ./args.sh 사과 배 복숭아
 
# vi check.sh
----------------------------------------------------------------------------------
#!/bin/bash
# 스크립트명 : check.sh
 
name=${1:?"이름 아규먼트가 필요합니다." }
echo 안녕하세요 $name님.
----------------------------------------------------------------------------------
# chmod +x check.sh
# ./check.sh 홍길동
 
  ※ 특수 함수 변경자인 :?는 $1의 위치 파라미터가 있는지 체크한다. 
 
>> $*와 $@의 차이
  $*와 $@는 큰따옴표로 둘러싸이면 다른 의미를 가진다. 큰따옴표로 둘러싸인 $* 변수는 파라미터 목록이 하나의 문자열이 된다.
  큰따옴표로 둘러싸인 $@ 변수는 각 파라미터들이 인용되고 각 단어는 분리된 문자열로 취급된다.
  $* : 작은 따옴표로(' ') 묶어도띄어쓰기를 하나의 값으로 보고 출력
  "$*" : 한 줄에 모두 출력
  $@ :  작은 따움표로(' ') 묶어도 띄어쓰기를 하나의 값으로 보고 출력
  "$@" : 작은 따움표로(' ') 묶으면 하나의 값으로 인식하며, 각 각 다른 행으로 출력
※ 파라미터들의 따옴표 형식을 인식하기 위해서는 "$@" 형식을 사용해야 한다.
  
조건문과 분기문
 
-종료상태: 명령어 수행 후에 echo $?을 입력하여 0이 나오면 정상 종료, 1이 나오면 비정상 종료(명령어 수행X)이다.
 
-싱글 브라켓([ ])과 test 명령: bash 2.x 버전에서 더블 브라켓 ([[ ]])은 표현식을 판단하기 위해 사용될 수 있으며, 시작
  브라켓 다음에는 공백이 존재해야 한다. test 명령에서는 논리 연산자 &&(AND)와 ||(OR)는 -a와 -o 연산자를 사용한다.
 
test 명령 연산자
참일 때(true)
문자열 테스트
[ string1 == string2 ]
문자열1과 문자열2의 값이 같은지 테스트한다.
[ string1 = string2 ]
단일= 기호는 bash 2.x 버전 이상에서 사용할 수 있다.
[ string1 != string2 ]
문자열1과 문자열2의 값이 다른지 테스트한다.
[ string ]
문자열이 null이 아닌지 테스트한다.
[ -z string ]
문자열의 길이가 0인지 테스트한다.
[ -n string ]
문자열의 길이가 0이 아닌지 테스트한다.
[ -l string ]
문자열의 길이(문자의 개수)
논리적 테스트
[ string1 -a string2 ]
string1과 string2가 모두 true인지 테스트한다.
[ string1 -o string2 ]
string1과 string2 둘 중 하나라도 true인지 테스트한다.
[ ! string1 ]
string1과 매칭되지 않는지 테스트한다.
논리적 테스트(복합적)
[[ pattern1 && pattern2 ]]
패턴1과 패턴2 모두 true인지 테스트한다.
[[ pattern || pattern2 ]]
패턴1과 패턴2 둘 중 하나라도 true인지 테스트한다.
[[ ! pattern ]]
패턴과 매칭되지 않는지 테스트한다.
정수형 테스트
[ int1 –eq int2 ]
int1과 int2가 같은지 테스트한다.
[ int1 –ne int2 ]
int1과 int2가 다른지 테스트한다.
[ int1 –gt int2 ]
int1이 int2보다 큰지 테스트한다.
[ int1 –ge int2 ]
int1이 int2보다 크거나 같은지 테스트한다.
[ int1 –lt int2 ]
int1와 int2보다 작은지 테스트한다.
[ int1 –le int2 ]
int1이 int2보다 작거나 같은지 테스트한다.
파일 테스트를 위한 바이너리 연산자
[ file1 –nt file2 ]
file1이 file2보다 최근 파일(수정 일자)인지 테스트한다. 최근 파일7이라면 true이다.
[ file1 –ot file2 ]
file1이 file2보다 이전 파일인지 테스트한다.
[ file1 –ef file2 ]
file1과 file2가 같은 디바이스 또는 아이노드(inode) 번호를 가지고 있는지 테스트한다. 같다면 true이다.
  
# name=centos  -> 변수 선언
# test $name != centos  -> name변수의 값이 centos와 같지 않는지 테스트
# echo $?
# [ $name = [CY]???? ]  -> name변수의 값이 C나 c로 시작하는 5자리인지 테스트
# echo $?
# x=10 ; y=20
# [ $x -gt $y ]  -> x가 y보다 큰지 테스트
# echo $?
# [ $x -le $y ]  -> x가 y보다 작거나 같은지 테스트
# echo $?
 ※ 브라켓을 사용할 때에는 반드시 시작 브라켓 다음에는 공백이 있어야 한다.
 
-let 명령과 이중 괄호의 산술 연산
# x=5; y=7;
# (( x > 2 ))
# echo $?  
# (( x < 2 ))
# echo $? 
# (( x == 5 && y == 7 ))
# echo $?
 
-if 명령
<형식>
if 명령
then
     명령
     명령
fi
 
# name=test
# if grep "$name" /etc/passwd > dev/null 2>&1
> then
> echo Found $name.또는
> fi
 -> 만약 /etc/passwd 파일에 test가 있으면 Found test.를 출력(Found test.)
 
# vi if.sh
----------------------------------------------------------------------------------
#!/bin/bash
echo "Are you o.k. (y/n) ?"
read answr
if [ "$answer" = Y -o "$answer" = y ]
then
     echo "y 라고 대답하셨네요. "
fi
----------------------------------------------------------------------------------
# chmod +x if.sh
# ./if.sh
 
# vi if!.sh
----------------------------------------------------------------------------------
#!/bin/bash
echo "Are you o.k. (y/n) ?"
read answer
if [[ $answer == [Yy]* || $answer == Maybe ]]
then
     echo "y 라고 대답하셨네요."
fi
----------------------------------------------------------------------------------
# chmod +x if1.sh
#./if1.sh
 
----------------------------------------------------------------------------------
#!/bin/bash
 
shopt -s extglob
answer="not really"
if [[ $answer = [Nn]o>( way|t really) ]]
then
     echo "Match. "
fi
----------------------------------------------------------------------------------
# chmod +x if2.sh
#./if2.sh
 
※ shopt -s extglob  -> 확장되 패턴 매칭 특징이 가능
 
- exit 명령과 ? 변수
# vi exitfile.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
# 이 스크립트는 / 파티션 아래에서 주어진 이전 날짜에(30일 미만)
# 변경되지 않은 파일을 검색하는 것입니다.(20블록 이상)
# (1block=512byte)
 
if (( $# != 2))  # [ $# -ne 2 ]
then
     echo "사용법:     $0 기간(30일 미만) 크기(20블록 이상) " 1>&2
     exit 1
fi
 
if (( $1 < 0 || $1 > 30 ))  # [ $1 -lt 0 -o $1 -gt 30 ]
then
     echo "30일 이전만 가능 : 시간이 초과되었습니다."
     exit 2
fi
 
if (( $2 <= 20 ))  # [ $2 -le 20 ]
then
     echo "파일 사이즈 범위가 20블록보다 작습니다. (20블록 이상)"
     exit 3
fi
 
find / -xdev -mtime $1 -size |$2
----------------------------------------------------------------------------------
# chmod +x exitfile.sh
# ./exitfile.sh
 
 -> find 명령은 파일을 검색하라는 명령이며, -mtime 옵션을 사용하여 $1 변수값의 이전 날짜를 의미하고, -size 옵션을 사용하여
  $2 변수값의 크기(block)를 의미한다. +$2이므로 $2의 값 이상인 파일을 검색한다는 의미이며 exit 1,2,3은 종료 상태의 값을 나타낸다.
 
# vi nullcheck.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
name=$1
if [ "$name" == " " } # [ ! "$name" } 또는 [ -z "$name" ]
then
     echo "첫 번째 아규먼트의 값을 입력하지 않았다. (null)"
else
     echo "첫 번째 아규먼트의 값은 $name이다."
fi
----------------------------------------------------------------------------------
# chmod +x nullcheck.sh
# ./nullcheck.sh  -> 첫 번째 아규먼트의 값을 입력하지 않았다. (null)
# ./nullcheck.sh pride  -> 첫 번째 아규먼트 값은 pride 이다.
 
-if/then/else 명령
<형식>
if 명령
then
     명령
else
     명령
fi
 
# vi ifelse.sh
----------------------------------------------------------------------------------
#!/bin/bash
# 스크립트명 : ifelse.sh
 
if [[ $1 == " " ]]
then
     echo 사용법 : ./ifelse.sh 아이디
     exit 1
fi
 
if grep :$1: /etc/passwd >& /dev/null
then
     echo $1 아디를 찾았습니다.
else
     echo "$1 아이디를 찾지 못했습니다."
     exit 2
fi
----------------------------------------------------------------------------------
# chmod -x ifelse.sh
# ./ifelse.sh
# ./ifelse.sh root
 
vi rootcheck.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
# 스크립트명: rootcheck.sh
# 수퍼유저의 유저아이디 번호는 0버이다.
 
id=`id | awk -F'[=(]'  '{print $2}' ` # 유저아이디 얻기
echo 유저아이디 번호 : $id
if (( id == 0 ))  # [ $id -eq 0 ]
then
     echo "당신은 수퍼유저입니다. "
else
     echo "당신은 수퍼유저가 아닙니다."
fi
----------------------------------------------------------------------------------
# chmod +x rootcheck.sh
# ./rootcheck.sh
 -> awk 이용하여 필드 구분자를 =또는 ( 기호를 사용한다. 그래서 1번 필드는 uid 문자열이 되고, 2번 필드는 0, 3번 필드는
    root)gid 문자열이 된다.
 
-if/then/elif/then/else 명령
<형식>
if 명령
then
     명령
elif 명령
then
     명령
else
     명령
fi
 
# vi qa.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
# 스크립트명 : qa.sh
 
echo -n "몇 점이세요? (0-100) : "
read num
if [ $num -lt 0 -o $num -gt 100 ]
then
     echo "0 이상 100 이하의 수를 입력하세요."
     exit 1
fi
 
if [ $num -le 69 ]
then
     echo "70점 이하네요. "
elif [ $num -ge 70 -a $num -le 79 ]
then
     echo "70점대군요."
elif [ $num -ge 80 -a $num -le 89 ]
then
     echo "80점대군요."
elif [ $num -ge 90 -a $num -le 99 ]
then
     echo "90점대군요"
elif [ $num -eq 100 ]
then
     echo "만점이시네요. 축하합니다. "
else
     echo "숫자를 입력해 주세요.(1-100)"
fi
----------------------------------------------------------------------------------
# chmod +x 
 
-파일테스트
 
<파일 테스크 연산자>
파일 테스트 연산자
참(true)일 때 의미
-b filename
파일이 존재하고 블록 특수 파일이면 참
-c filename
파일이 존재하고 문자 특수 파일이면 참
-d filename
파일이 존재하고 디렉터리이면 참
-e filename
파일이 존재하면 참
-f filename
파일이 존재하고 일반 파일이면 참
-G filename
파일이 존재하고 유효 그룹 ID의 소유이면 참
-g filename
파일이 존재하고 set-group-id이면 참
-k filename
파일에 “스틱키(sticky)” 비트가 설정되어 있으면 참
-L filename
파일이 존재하고 심볼릭 링크이면 참
-p filename
파일이 존재하고 명명된(named) 파이프이면 참
-L filename
파일이 존재하고 심볼릭 링크이면 참
-p filename
파일이 존재하고 읽을 수 있으면 참
-O filename
파일이 존재하고 유효(effective) 사용자 ID의 소유이면 참
-f filename
파일이 존재하고 읽을 수 있으면 참
-S filename
파일이 존재하고 소켓이면 참
-s filename
파일이 존재하고 그 크기가 0보다 크면 참
-t fd
fd(파일 기술자)가 열린 상태이고 터미널이면 참
-u filename
파일이 존재하고 set-user-id 비트가 설정되어 있으면 참
-w filename
파일이 존재하고 쓸 수 있으면 참
-x filename
파일이 존재하고 실행 가능하면 참
  
# vi permitest1.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
if [[ -z $1 ]]
then
     echo 사용법 : ./permtest1.sh 파일명
     exit 1
fi
 
if [[ -d $1 ]]
then
     echo "$1은 디렉터리다."
elif [[ -f $1 ]]
then
     if [[ -r $1 && -w $1 && -x $1 ]]
     then
          echo "$1 파일은 읽기, 쓰기, 실행이 가능한 파일이다. "
     fi
else
     echo "$1은 디렉터리도 파일도 아니다. "
fi
----------------------------------------------------------------------------------
# chmod +x permitest1.sh
# ./permitest.sh
# ./permitest.sh permitest.sh
 
-null 명령: 빌트인 명령이며, 콜론(:)으로 표시하며 수행시에 아무것도 출력하지 않는다.
 
# vi nulltest.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
if grep "$1" testfile > & /dev/null
then
     :
else
     echo "$1 문자열은 testfile에 없네요."
     exit 1
fi
----------------------------------------------------------------------------------
# chmod +x nulltest.sh
# ./nulltest.sh
# ./nulltest.sh 홍길동
 -> 입력값이 testfile의 1번째 필드의 아규먼트와 일치하는지 확인하고 있으면 아무것도 출력하지 않고 없으면 메세지를 출력한다.
 
# vi nulltest1.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
echo "정수를 입력하세요."
read number
if expr "$number" + 0 >& /dev/null
then
     :
else
     echo "입력된 값은 정수가 아닙니다."
     exit 1
fi
----------------------------------------------------------------------------------
# chmod +x nulltest1.sh
# ./nulltest1.sh
-> 정수를 입력하세요~
     1.22  -> "입력된 값은 정수가 아닙니다. "출력
     100 -> 변화없음
 
  입력값에 +0을 했을 때 정수이면 출력 없고 정수가 아니면 "입력된 값은 정수가 아닙니다"를 출력한다. 
  ※ expr: 표현식을 평가하는 명령어
 
-case 명령
<형식>
case 변수 in
value1)
     명령
;;
value2)
     명령
     ;;
*)
     명령
     ;;
esac
 
# vi case_exam.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
echo -n "색을 표현하는 영어단어를 적으세요. 한글로 번역합니다. : "
read color
case $color in
[Bb]l??)
     echo 푸른색입니다.
     ;;
[Gg]ree*)
     echo 녹색입니다.
     ;;
red | orange) # 버티컬바는 or를 의미한다.
     echo 빨간색 또는 오렌지색입니다.
     ;;
*)
     echo "다시 입력해 주세요(blue, green, red, orange). "
     ;;
esac
echo "Case 명령 실행을 완료했습니다. "
----------------------------------------------------------------------------------
# chmod +x case_exam.sh
# ./case_exam.sh
 
>> here 다큐먼트와 case 명령을 사용한 메뉴 생성
# vi case_exam2.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
echo "웹 서버를 시작할지 중지할지 선택하세요.:  "
cat <<- ENDIT
     1) 웹 서버 시작
     2) 웹 서버 중지
     3) 웹 서버 재시작
ENDIT
 
read choice
case "$choice" in
1) STATUS="시작"
     /etc/init.d/httpd start
     ;;
2) STATUS="중지"
     /etc/init.d/httpd stop
     ;;
3) STATUS="재시작"
     /etc/init.d/httpd restart
     ;;
esac
echo "웹 서버가 $STATUS되었습니다. "
----------------------------------------------------------------------------------
# chmod +x case_exam2.sh
# ./case_exam2.sh
 -> cat <<- ENDIT 명령은 cat 명령의 종료 마크로 ENDIT 문자열을 사용하는 here 다큐먼트이다. 즉, cat 명령으로 화면에 출력할
 문자열은 ENDIT 문자열로 시작하는 라인의 앞부분이다. 선택된 숫자를 choice 변수에 할당하고 변수에 값에 따라 서로 다른 명령어를
 지정하였다. 각 case 값에 대해 STATUS 변수값을 할당하고 실행할 명령들을 적어주었다.
 
루프 명령(for, while, until)
 
-for 루프 명령
<형식>
for 변수 in 단어목록
do
     명령
done
 
# vi forloop.sh
 
----------------------------------------------------------------------------------
#!/bin/bash
 
for loop in 홍길동 장길산 장보고 이순신
do
     echo "$loop"
done
echo "루프가 끝났습니다."
----------------------------------------------------------------------------------
# chmod +x forloop.sh
# ./forloop.sh
 -> 4개의 이름을 차례로 출력
 
#vi mail_list
---------------------------------------------------------------------------------
root
centos
---------------------------------------------------------------------------------
# vi mail.txt
---------------------------------------------------------------------------------
안녕하세요.
반갑습니다.
---------------------------------------------------------------------------------
# vi mailing.sh
---------------------------------------------------------------------------------
#!/bin/bash
 
for person in $(cat mail_list)
do
     mail $person < mail.txt
     echo $person 발송 완료
done
echo "전체 메일 발송 완료!"
----------------------------------------------------------------------------------
# chmod +x mailing.sh
# ./mailing.sh
 -> mail.txt의 내용을 mail_list에 있는 사용자에게 메일로 발송
 
 <백업 스크립트>
# touch file1 file2 file3
# mkdir backup
# vi backup.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
dir=/script/backup
for file in if*
do
     if [ -f $file ]
     then
          cp $file $dir/$file.bak
          echo "$file 파일이 $dir 디렉터리에 백업되었습니다."
     fi
done
----------------------------------------------------------------------------------
 -> for루프 사용하여 if로 시작하는 모든 파일을 file 변수에 할당하고 "-f $file"을 사용하여 파일인지 판단한 다음,
    파일이면 cp명령을 사용하여 파일을 복사하면서 파일 뒤에 .back 문자열을 붙이도록 하였다.
 
- $*와 $
 큰 따움표로 둘러 싸이지 않으면 $*와 $@의 의미는 같다. $* 하나의 문자열을, $@는 분리된 단어의 목록을 평가한다.
# vi hi.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
for name in $*
do
     echo $name 안녕.
done
----------------------------------------------------------------------------------
# chmod +x hi.sh
# ./hi.sh linux centos script
 -> linux안녕. centos안녕. script안녕  이 각 행에 출력됨
 
# vi permx.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
for file
do
     if [[ -f $file && ! -x $file ]]
     then
          chmod +x $file
          echo $file 파일에 실행퍼미션을 추가했습니다.
     fi
done
----------------------------------------------------------------------------------
# chmod +x permx.sh
# touch permxtest1 permxtest2 permxtest3
# ls -l permxtest*
# ./ permx.sh permxtest*  -> permxtest로 시작하는 파일들에게 실행권한(+x)을 부여함
# ls -l permxtest*
 -> for 루프에서 단어 목록 미지정시 스크립트가 실행될 때 위치 파라미터를 분리하여 file 변수에 할당한다. if 명령으로
    주어진 파일이 파일인지, 실행퍼미션을 가지고 있지 않은지 판단하고 두 가지 조건을 만족하면 퍼미션을 추가한다.
 
-while 루프 명령
<형식>
while 명령
do
     명령
done
 
# vi numbers.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
number=0 #number 변수 초기화
while (( $number < 10 )) # 또는 while [ number -lt 10 ]
do
     echo -n "$number"
     let number+=1 # number 변수 1증가
done
echo -e "\n루프 종료."
----------------------------------------------------------------------------------
# chmod +x number.sh
# ./number.sh
 -> 0부터 9까지의 숫자를 차례대로 출력함
 
# vi quiz.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
echo "2007년 12월 19일 제 17대 대한민국 대통령에 당선된 사람의 이름은?"
read answer
while [[ "$answer" != "이명박" ]]
do
     echo "정답이 아닙니다. 다시 입력해 주세요!"
     read answer
done
echo 정답입니다. :: 이명박
----------------------------------------------------------------------------------
# chmod +x quiz.sh
# ./quiz.sh
 -> answer 변수에 값을 저장하고 그 값이 "이병박"이 아니면 반복해서 입력받고, 맞으면 메세지를 출력 후 종료
 
# vi say.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
echo q를 입력하면 종료합니다.
go=start
while [[ -n "$go" ]]  # 변수에 큰 따옴표를 확인하라.
do
     echo -n 종료하려면 q를 입력하세요. :
     read word
     if [[ $word == [qQ] ]]  # 예전 스타일 : [ "$word: = q -o :$word: = Q ]
     then
          echo "q를 입력하셨네요. 종료합니다!"
          go=
     fi
done
----------------------------------------------------------------------------------
# chmod +x say.sh
# ./quiz.sh
 -> go의 변수의 값이 null이 아니면 루프를 계속 수행한다. 만약 q가 입력되면 then 아래의 명령이 수행되어 go  변수의 값이
   null이 되므로 while 루프를 빠져나가게 된다.
 
-until 루프 명령
<형식>
until 명령
do
     명령
done
 
vi untilcommand.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
until who | grep multi
do
     sleep 5
done
echo multi 유저가 로그인해 있습니다.
----------------------------------------------------------------------------------
# chmod +x untilcommand.sh
# ./untilcommand.sh
 -> root유저가 로그인 할때까지 who 명령어를 5초에 한번씩 실행했다. root 유저가 있으면 who명령어 실행 후 종료한다.
 
# hour.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
hour=0
until (( hour >= 24 ))
do
     case "$hour" in
     [0-9]|1[0-1]) echo $hour시 : 오전
     ;;
     12) echo $hour시 : 정오
     ;;
     *) echo $hour시 : 오후
     ;;
     esac
     (( hour+=1 ))  # hour 변수를 1 증가해야 한다.
done
----------------------------------------------------------------------------------
# chmod +x hour.sh
# ./hours.sh
 -> 0부터 23까지의 각 숫자에 해당하는 case 명령의 echo 명령 결과를 출력(0~11시 : 오전, 12시 : 정오, 13~23시 : 오후로 출력)
 
-select 명령과 메뉴: PS3 프로픔트는 입력을 위해 사용하는데, 디폴트로 PS3은 #?이다. PS 프롬프트가 출력된 다음, 쉘은 사용자의
입력을 위해 기다리게 된다. 이때 입력값은 메뉴 목록의 숫자 중에 하나가 되어야 한다. case 명령은 메뉴와 선택, 명령, 실행으로부터
유저가 선택하도록 하는 select 명령과 함께 사용된다. (루프를 빠져나가기 위해서는 break, 스크립트를 종료하기 위해서는 exit 사용)
<형식>
select 변수명 in 단어목록
do
     명령
done
 
# vi run.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
PS3="실행할 프로그램을 선택하세요. : "
select program in 'ls -F' pwd date exit
do
     $program
done
----------------------------------------------------------------------------------
# chmod +x run.sh
# ./run.sh
 -> 1을 입력하면 'ls -F', 2를 입력하면 pwd, 3을 입력하면 date, 4를 입력하면 exit를 실행한다.
 
# vi choice.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
PS3="번호를 입력하면 웹사이트 주소를 볼 수 있습니다.. : "
select choice in 구글 네이버 네이버닷컴 다음 종료
do
     case "$choice" in
     구글)
          echo "구글 - http://www.google.com"
          continue;;
     네이버 | 네이버닷컴)
          echo "네이버 - http://www.naver.com"
          continue;;
     다음)
          echo "다음 - http://www.daun.net"
          continue;;
     종료)
          echo "종료하였습니다."
          break;;
     *)
          echo "$REPLY은(는) 없습니다. 1에서 4사이의 수를 입력하세요." 1>&2
          echo "다시 선택."
          ;;
     esac
done
----------------------------------------------------------------------------------
# chmod +x choice.sh
# ./choice.sh
 -> 검색사이트들의 이름에 해당하는 번호를 선택하면 웹사이트의 주소를 출력해 주는 스크립트이다. select 명령어에서 변수로
   choice를 사용했으며, 이 변수에 할당된 값은 총 5가지로 구성하였다. 선택한 번호가 존재하지 않을 경우 REPLY 빌트인 변수를
   사용하여 echo 메시지를 출력하도록 하였으며 5번을 선택하면 break;; 명령을 실행하여 do~done을 빠져나온다.
   값 입력 후에 continue를 수행함으로써 반복적인 입력을 수행 할 수 있다.
 
루프 관리 명령
-shift 명령: shit 명령은 지정한 수만큼 좌측으로 파라미터 목록을 이동한다. 가장 좌측에 있는 파라미터는 영구적으로 삭제된다.     
<형식>
shitf n
 
# vi shift_using.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
set 사과 배 포도 복숭아
shift
echo $*
set $(date)
echo $*
shift 3
echo $*
shift
echo $*
----------------------------------------------------------------------------------
# chmod +x shift_using.sh
./shift_using.sh
 -> 결과값은 "배 포도 사과", date 출력값, date의 4번째 파라미터부터, date의 5번째 파라미터부터 출력($*은 모든 파라미터 출력)
 
# vi shift_while.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
while (( $# > 0 ))
do
     echo $*
     shift
done
----------------------------------------------------------------------------------
# chmod +x shift_while.sh
# ./shift_while.sh 사과 배 복숭아
 -> 파라미터의 수가 0보다 크면 do~done 명령을 수행한다. 즉, 입력받은 파라미터의 수가 0이 될때까지 shift하여 출력한다.
 
# vi shift_date.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
set $(date)
while (( $# > 0 ))
do
     echo $1
     shift
done
----------------------------------------------------------------------------------
# chmod +x shift_date.sh
# ./shift_date.sh
 -> 파라미터의 수가 0보다 같거나 작을 때 까지 shft를 수행하면서 1번째 파라미터를 출력한다.
 
-break 명령: break 명령은 루프를 빠져나가기 위해 사용한다. 바깥쪽 루프부터 안쪽 루프까지 3,2,1이 된다.
<형식>
break n
 
# vi loop_break.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
while true
do
     echo "리눅스를 사용해 보신 적이 있나요[y/n]? : "
     read answer
     if [[ "$answer" == [Y|y] ]]
     then
          break
     else
          echo "리눅스를 사용해 보신 경험이 없군요. "
     fi
done
echo "리눅스 사용자이시군요."
----------------------------------------------------------------------------------
# chmod +x loop_break.sh
# ./loop_break.sh
 -> 입력값이 Y또는 y가 될때까지 무한루프를 수행한다.
          
-continue 명령: 상태값이 true가 되면 continue 아래의 모든 명령들은 무시되고 루프의 최상위로 리턴하는 명령이다.
  만약에 3개의 중첩루프가 있다면 가장 바깥쪽 루프는 3, 그 안쪽은 3, 가장 안쪽은 1로 정의된다. 가장 바깥쪽 루프의 상위로
  가려면 continue 3을 실행하면 된다.
<형식>
continue n
 
# vi mail_list
----------------------------------------------------------------------------------
apache2
root
----------------------------------------------------------------------------------
# vi mail_content.txt
----------------------------------------------------------------------------------
안녕하세요
메일 테스트입니다.
----------------------------------------------------------------------------------
 
# vi continue_mail.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
for name in $(cat mail_list)
do
     if [[ $name == apache2 ]]
     then
          continue
     else
          mail $name < mail_content.txt
     fi
done
----------------------------------------------------------------------------------
# chmod +x continue_mail.sh
# ./continue_mail.sh
# mail
 -> mail_list애 입력되어 있는 유저 아이디를 가져와서 name 변수에 할당하는데, 이때 name 변수의 값이 apache2라면  coninue 
 명령을 실행하여 루프 최상단으로 가기 때문에 apache2 유저에게는 메일을 발송하지 않고 root 유저에게만 메일을 발송한다.
 
-중첩 루프와 루프 관리: 중첩 루프를 사용할 때 break 명령과 continue 명령에 숫자(정수형 아규먼트)를 부여할 수 있다.
<형식>
continue n : n번째 루프의 시작으로 이동
n : 가장 안쪽 루프가 1
     그 다음 바깥쪽 루프가 2
     그 다음 바깥쪽 루프가 3 ...
 
# vi loop_continue2.sh
----------------------------------------------------------------------------------
#!/bin/bash
# "continue n" 명령, n번 레벨의 루프에서 계속하기(continue).
 
for outer in A B C D E  # 바깥쪽 2번 루프
do
     echo; echo -n "Group $outer: "
     for inner in 1 2 3 4 5 6 7 8 9 10  # 안쪽 1번 루프
     do
          if [ "$inner" -eq 6 ]
then
          continue 2  # "바깥쪽 루프"인 2번 루프에서 계속 진행한다..
                           # 윗줄을 "continue"라고 하면 안쪽 1번 루프를 순회한다.
          fi
          echo -n "$inner" # 5 7 8 9 10은 출력되지 않는다.
     done
done
echo; echo
exit 0
----------------------------------------------------------------------------------
# chmod +x loop_continue2.sh
# ./loop_continue2.sh
 -> 안쪽 루프의 inner 변수의 값이 1부터 5까지 출력된 다음, 6이 되면 continue2 로 진행하여 반복적으로 수행하기 때문에
     6부터 10까지의 수는 출력되지 않는다.
 
리다이렉션과 서브쉘
 
-루프의 결과를 파일로 리다이렉트하기
# vfi file.txt
----------------------------------------------------------------------------------
홍길동: 100
장길산: 200
정약용: 300
----------------------------------------------------------------------------------
# vi redirectfile.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
if (( $# < 2 ))
then
     echo "Usage: $0 [입력 파일명] [출력 파일명]" >&2
     exit 1
fi
 
count=1
cat $1 | while read line
do
     ((count == 1 )) && echo "Processing file $1..." > /dev/tty
     echo -e "$count\t$line"
     let count+=1
done > tmp$$
mv tmp$$ $2
----------------------------------------------------------------------------------
# chmod +x redirectfile.sh
# ./redirectfile.sh
# ./redirectfile.sh file.txt file2.txt
# cat file2.txt
 -> 라인별로 앞쪽에 라인 번호가 입력되고 탭이 들어간 다음 원래의 문자열이 출력된다.
 
-루프의 결과를 명령어와 파이프하기
# vi loop_command.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
for i in 9 4 2 6 7 3
do
     ecgi $i
done | sort -n
----------------------------------------------------------------------------------
# chmod +x loop_command.sh
# ./loop_command.sh
 -> sort -n 명령을 사용하여 숫자를 정렬하여 출력
 
-백그라운드에서 루프 사용하기
----------------------------------------------------------------------------------
#!/bin/bash
 
for person in root multi linux centos
do
     mail $ person < mail.txt
done &
----------------------------------------------------------------------------------
 -> &를 사용하면 for 루프를 백그라운드로 실행할 수 있다.
 
-IFS와 루프: 쉘의 내부 필드 분리자(IFS)는 공백, 탭, newline 문자를 평가하며, read, set, for와 같은 단어 목록을 분석하는
명령을 위해 단어 분리자로 사용된다. (분리자 재설정 가능)
# vi use_IFS.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
names=홍길동:김길동:이길동:박길동
oldifs="$IFS"
IFS=":"
for persons in $names
do
     echo $persons님 안녕하세요.
done
 
echo "====="
IFS="$oldifs"
set 박정희 김대중 노무현 이명박
 
for president in $*
do
     echo $president님 안녕하세요
done
----------------------------------------------------------------------------------
# chmod +x user_IFS.sh
# ./user_IFS.sh
 -> names 변수에 값을 할당하면서 콜론:) 문자를 분리자로 사용하여 4개의 이름을 할당하였다. 그리고 IFS변수를 나중에
   사용하기 위해 oldifs 변수에 할당해 주었으며, IFS 변수에는 콜론(:)을 재할당하였다. 그리고 for루프에서 names 변수
   에서 방금 할당한 IFS 변수의 값인 콜론(:)을 사용하여 persons 변수에 분리된 문자열을 할당한다. 이번에는 앞서 만들
   어둔 oldifs 변수의 값을 다시 IFS 변수에 재할당한 다음, set 명령을 사용하여 위치 파라미터들을 지정하고 $1 $2 $3 $4,
   for 루프에서 $* 전체 위치 파라미터들을 president 변수에 각각 할당하면 공백을 기준으로 파라미터들이 분리되어 출력된다.
 
함수: 함수는 명령 또는 명령 그룹의 명칭이다. 함수는 현재 쉘의 컨텍스트에서 실행되며 자식프로세스를 생성하지
 않는다.
<함수 작성 규칙>
 1. 쉘은 디스크에서 검색되는 엘리아스, 함수, 빌트인 명령, 실행 프로그램(스크립트)들을 사용할지 결정한다.
 2. 함수를 사용하기 위해서는 가장 먼저 함수를 정의해 두어야 한다.
 3. 함수는 현재 환경에서 실행된다. 함수를 호출하는 스크립트 내에서 변수를 공유하여 위치 파라미터로 할당된 아규먼트들을
    전달한다. 로컬 변수는 local 함수를 사용하여 함수 내에서 생성할 수 있다.
 4. 만약 함수에서 exit 명령을 사용하면 스크립트의 실행을 중지하고 빠져나간다.
 5. 함수에서 return 문장은 함수 또는 주어진 아규먼트의 값으로 마지막 실행된 명령의 종료상태를 리턴한다.
 6. 함수는 export -f 빌트인 명령을 사용하여 서브쉘로 전달(전역화)할 수 있다.
 7. 함수 목록과 정의를 출력하기 위해서는 declare -f 명령을 사용하고 함수 이름 목록을 출력하기 위해서는 decalre -F 명령을
    사용한다.
 8. 변수와 같이 트랩은 함수 안에서 전역이다. 스크립트와 스크립트에서 호출되는 함수에 의해 공유된다. 만약 트랩이 함수에서
     정의되었다면 스크립트에 의해 공유된다. 원하지 않는 효과를 가져올 수 있다.
 9. 만약 함수가 다른 파일에 저장되어 있으면 source 명령을 사용하여 현재 스크립트에서 사용할 수 있다.
10. 함수는 재귀호출이 가능하다. 즉, 자신을 호출할 수 있으며 재귀호출 횟수는 제한이 없다.
<형식>
function 함수명 { 명령 ; 명령 ; }
# function dir { echo "Directories: ";ls -l | awk '/^D/ {print $NF}' ; }
# dir
 
-함수 설정 제거하기
<형식>
 
unset -f 함수명
# function kty { echo "KIM TAE YONG" ; }
# kty
# unset -f
# kty 
 
-함수 export: 함수를 서브쉘로 export하여 서브쉘에서 함수를 사용할 수 있다.
<형식>
export -f 함수명
 
-함수 아규먼트와 리턴값
>> 아규먼트: 아규먼트는 위치 파라미터를 사용하여 함수로 전달 할 수 있다
>> 빌트인 local 함수: 로컬 변수는 함수 내에서만 사용하는 변수이며, local 함수를 사용하여 로컬 변수를 정의한다. 함수가 종료
    되면 로컬 변수도 제거된다.
>> 빌트인 return 함수
    return 명령은 함수를 종료하기 위해 호출되는 함수의 위치에서 프로그램 관리를 리턴하는데 사용할 수 있다. (스크립트나 함수
   에서 exit 명령을 사용하면 스크립트를 종료함). return 명령을 사용하여 아규먼트를 지정하지 않으면 함수의 리턴값은 스크립트
   에 사용된 마지막 명령의 종료상태값이 된다. 만약 return 명령에 의해 할당된 값이 있다면 그 값은 ? 변수에 저장되고 0~256
   사이의 정수값을 가질 수 있다.
 
# vi rwcheck.sh
----------------------------------------------------------------------------------
#!/bin/bash
function Usage { echo "에러 : $*" 2>&1; exit 1; }
if (( $# != 2 ))
then
     Usage "$0: 두 개의 아규먼트가 필요합니다. "
fi
if [[ ! ( -r $1 && -w $1) ]]
then
     Usage "$1: 파일은 읽고 쓸 수 없습니다. "
fi
echo 아규먼트 : $*
----------------------------------------------------------------------------------
# chmod +x rwcheck.sh
# touch f1.txt f2.txt
# ls -l f1.txt f2.txt
# ./rwcheck.sh
# ./rwcheck.sh f1.txt f2.txt
 -> 에러가 발생했을 때 아규먼트를 사용하여 메세지를 출력하는 함수이다. 만약 아규먼트의 수가 2개가 아니라면 then 이하의 
    Usage 함수 호출을 실행하여 에러 메시지를 출력할 것이며, if 명령어에서 일고 쓰기가 불가능하다면 then 이하의 Usage 함수를
    호출할 것이다. [결과 -> 아규먼트 : f1.txt f2.txt]
 
# vi increase.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
increase () {
     local sum;
     let "sum=$1 + 1 "
     return $sum
}
echo -n "합계는 "
increase 7
echo $? # increase 함수의 리턴값을 출력함
echo $sum # 아무런 값도 출력하지 않음
----------------------------------------------------------------------------------
# chmod +x increase.sh
# ./increase.sh
 -> 아규먼트가 7인 increase 함수를 호출하여 7+1의 결과값을 리턴해준다. (결과 -> 합계는 8)
 
# square.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
function square {
     local sq
     let "sq=$1 * $1"
     echo "가로와 세로 길이 : $1"
     echo "정사각형 넓이 : $sq "
}
echo "정사각형의 가로는? "
read number
value_returned=$(square $number)
echo "$value_returned"
----------------------------------------------------------------------------------
# chmod +x square.sh
# ./square.sh
 -> sq를 지역변수로 선언하여 첫번째 입력값의 곱을 할당하고 입력 된 값을 read 명령을 사용하여 number 변수에 할당하였다.
    square 함수에서 이 값을 아규먼트로 사용하여 호출한 결과값을   value_returend 변수에 할당하고 이 변수값을 출력하였다
 
-함수와 source 명령: 함수가 필요할 때 source 명령을 사용하여 함수가 정의된 파일에서 호출하여 사용할 수 있다.
# vi myfunction
----------------------------------------------------------------------------------
function os () {
     echo "리눅스"
}
----------------------------------------------------------------------------------
# function use() { echo $1님은 $(os)를 사용해 보셨나요?; }
# source myfunction
# os
# use root
 -> 쉘에서 source 명령을 사용하여 myfunction 파일을 읽어들일 수 있고, use 함수에도 함께 적용하여 사용할 수 있다.
 
# vi function
----------------------------------------------------------------------------------
function A() {
     echo "function A"
}
function B() {
     echo "function B"
}
function C() {
     echo "function C"
}
----------------------------------------------------------------------------------
 
# vi function_script.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
source ./function
A # 함수 A 실행
B # 함수 B 실행
C # 함수 C 실행
----------------------------------------------------------------------------------
# chmod +x function_script.sh
# ./function_script.sh
# A
 -> 쉘 스크립트 내부에서 사용한 함수는 스크립트가 종료되면 모두 제거되기 때문에 실행 완료 후에는 사용할 수 없다.
 
트래핑 시그널
-trap 명령은 시그널이 도착했을 때 프로그램이 어떤 반응을 할지 관리하도록 하는 명령이다.
 kill -l 명령 또는 trap -l 명령을 사용하면 모든 시그널 목록을 볼 수 있다.
※ 가장 많이 사용하는 시그널
   1) SIGHUP (hangup), 2) SIGINT (interrupt), 3) SIGQUIT(quit), 9) SIGKILL (kill) 15) SIGTERM(exit), 20) SIGTSTP (stop)
<형식>
trap '명령; 명령' 시그널번호
trap '명령; 명령' 시그널이름
 
# trap 'rm tmp*; exit 1' 1 2 15
 -> 1, 2, 15 시그널이 도착했을 때 tmp로 시작하는 모든 파일을 삭제하고 종료하도록 한 것이다. 스크립트가 실행되는 동안 인터
    럽트가 발생하면 tarp 명령은 시그널을 인터럽트하게 된다. 
# trap 'rm tmp*; exit 1' HUP INT TERM
 -> bash쉘에서는 SIG 문자열을 제외한 시그널 심볼릭 이름을 사용 할 수 있으며, 시그널의 숫자값도 사용할 수 있다.
 
-시그널 재설정
시그널을 디폴트로 설정하기 위해서 TRAP 명령 다음에 시그널 이름 또는 시그널 번호를 적는다. 
 (함수의 trap 설정은 함수가 호출 될 때 함수를 호출한 쉘에 한 번만 적용된다)
 trap INT 또는 trap 2
 -> 시그널 2를 위한 디폴트 액션을 리셋하였다. 이 디폴트 액션은 <Ctrl-C> 키를 두 번 눌러서 인터럽트할 때 프로세스를 제거
    하기 위한 것이다.
 trao 'trap 2' 2
 -> 실행할 명령어를 (' ')로 감싸주었기 때문에 프로그램을 종료하기 위해서는 <Ctrl-C>키를 두 번 눌러야 한다. 먼저 첫 번째
     trap은 시그널을 가로채고, 두 번째 trap 재설정은 시그널의 디폴트 액션으로 설정하여 프로세스를 제거하는 것이다.
 
-시그널 무시하기
 trap 명령 다음 따옴표 안에 아무 내용이 없으면 시그널 목록들은 프로세스에 의해 무시된다.
 trap 명령 " " 1 2 또는 trap "" HUP INT
 -> 시그널 1과 2는 쉘 프로세스에 의해 무시된다.
 
-trap 목록
# vi trap_exam.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
trap 'echo "Ctrrl-C 종료하지 않음 $0."' INT
trap 'echo "Ctrl-\\ 종료하지 않음 $0."' QUIT
trap 'echo "Ctrl-Z 종료하지 않음 $0."' TSTP
echo "프롬프트에 아무 문자열이나 입력하세요.
종료를 하려면\"stop\" 을 입력하세요."
 
while true
do
     echo -n "GOGO...> "
     read
     if [[ $REPLY == [Ss]top ]]
     then
          break
     fi
done
----------------------------------------------------------------------------------
# chmod +x trap_exam.sh
# ./trap_exam.sh
GOGO...> Ctrl-C, Ctrl-\, Ctrl-Z, stop을 차례로 입력
 ->  Ctrl-C, Ctrl-\, Ctrl-Z 키에 echo를 설정하여 시그널을 수행하지 않고 메세지를 출력하게 함(stop 입력시 종료)
 
-trap과 함수: trap을 사용한 함수가 한번 호출되고 나면 스크립트 전체에 영향을 미친다.
# vi trap_func.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
function trapper () {
     echo "trapper 안"
     trap 'echo "trap이 가로챔!"' INT
     # trap이 한번 설정되면 trap은 스크립트 전체에 영향을 준다.
     # ^c를 입력하더라도 스크립트는 무시한다.
}
 
 
while :
do
     echo "메인 스크립트 안에서"
     trapper
     echo "아직 메인 스크립트"
     echo "프로세스 아이디(ID) : $$"
     sleep 5
done
----------------------------------------------------------------------------------
# chmod +x trap_func.sh
# ./trap_func.sh
 <Ctrl-c> 입력
 <Ctrl-z> 입력
# jobs
# ps ax | grep trap_func.sh | grep -v grep
# kill -9 [PID]
# ps ax | grep trap_func.sh | grep -v grep
 -> trapper 함수를 정의하여, 시그널 INT(^C)가 발생하면 "trap이 가로챔"이라는 문자열을 출력하도록 하였고 메인 스크립트에서
    while 무한루프 상태에서 trapper 함수를 호출하고 현재 프로세스 아이디를 출력하도록 하였다. 프로세스를 종료시키기 위해
    서는 <Ctrl-C>키를 사용하여 프로세스를 백그라운드에서 실행되도록 한 다음 kill -9 명령을 입력하여야 한다.
 
bash 스크립트 디버깅
<bash 스크립트 디버깅 옵션>
스크립트 디버깅 옵션
옵션명
설명
bash –x 스크립트명
에코 옵션
변수 치환 후 그리고 실행 이전에 스크립트 각 라인을 출력한다.
bash –v 스크립트명
다양한 옵션
실행 이전에 스크립트의 각 라인을 출력한다.
bash –n 스크립트명
비실행 옵션
해석은 하지만 실행하지는 않는다.
set –x
에코 활성화
스크립트에서 실행을 추적한다.
set +x
에고 비활성화
스크립트에서 실행을 추적하지 않는다.  
※ 다양한 옵션을 사용하거나 -v 옵션(bash -v 스크립트명)과 함께 쉘을 호출하면 스크립트의 각 라인은 스크립트에 타이핑한
  것처럼 출력하고 실행 할 수 있다.
 
# debug_exam.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
name="linux"
if [[ $name == "centos" ]]
then
     printf "Hello $name\n"
fi
 
declare -i num=1
while(( num < 5 ))
do
     let num+=1
done
printf "Total : %d\n" $num
----------------------------------------------------------------------------------
# bash -x debug_exam.sh  -> 변수 치환 후 실행 이전에 스크립트의 각 라인을 출력
# chmod +x debug_exam.sh
# ./debug_exam.sh
     
명령라인
 
-getopts를 사용한 명령라인 프로세싱: -옵션을 사용 할때 여러개의 아규먼트를 한번에 처리 할 수 있다.(ls -liF)
 
# vi opt1.sh
----------------------------------------------------------------------------------
while getopts xy options
do
     case $options in
          x ) echo "-x 옵션을 사용하셨네요.";;
          y ) echo "-y 옵션을 사용하셨네요.";;
     esac
done
----------------------------------------------------------------------------------
# chmod +x opt1.sh
# ./opt1.sh -x
# ./opt1.sh -xy
# ./opt1.sh -a
# ./opt1.sh a
 -> getopts 명령은 x와 y의 옵션을 체크하기 위해 getopts xy 형태로 사용한다. -x와 -y는 있는 옵션이기 때문에 입력시에 
    정상적으로 출력되지만 -a는 옵션으로 인식하지 않기 때문에 잘못된 메세지를 출력,-가 없으면 아무값도 출력하지 않는다.
 
-툭수한 getopts 변수들: getopts 함수는 아규먼트들의 존재를 유지시키기 위해 두 개의 변수(OPTIND,OPTARG)를 제공한다.
 OPTIND 변수는 1로 초기화되며, getopts가 명령라인 아규먼트를 한번 씩 프로세싱 할 때마다 증가되는 특수변수이다.
 OPTARG 변수는 아규먼트의 값을 가진다.
 
# vi opt3.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
while getopts ab: options
do
     case $options in
          a) echo "-a 옵션을 사용하셨네요.";;
          b) echo "-b 옵션의 아규먼는 $OPTARG";;
          c) echo "사용법 : opt3 -ab 파일명" 1>&2;;
     esac
done
----------------------------------------------------------------------------------
# chmod +x opt3.sh
# ./opt3.sh -a
# ./opt3.sh -b linux
 -> -a 옵션을 입력하면 지정된 메세지를 출력하고 -b 옵션과 파라미터를 입력하면  OPTARG에 저장하여 출력한다.
 
-eval 명령과 명령라인 파싱: eval 명령은 명령라인을 평가하는데, 모든 쉘 치환을 수행한 다음 명령라인을 실행한다.
# set a b c d e  -> 파라미터 5개 설정
# echo The Last Argument is \$$#.  -> "\$"는 $문자를 그대로 출력, $#의 값은 파라미터 개수를 출력 (출력값: $5)
# eval echo The Last Argument is \###.  -> eval 명령을 사용하면 변수를 먼저 값으로 치환한 다음에 echo 명령을 수행
 
vi eval_exam.sh
----------------------------------------------------------------------------------
#!/bin/bash

eval `id | sed 's/[^a-z0-9=].*//'`
if [ "${uid:=0}" -ne 0 ]
then
     echo $0: only root can run $0
     exit 2
else
     echo "root user : superuser"
fi
----------------------------------------------------------------------------------
# chmod +x eval.exam.sh
# ./eval_exam.sh
# su fedora
# ./eval_exam.sh
# exit
 -> sed 명령어를 사용하여 정규표현식은 문자열로 시작되고 = 기호가 있는 곳까지 검색한다. 그리고 괄호가 나타나는 곳부터 
    문장의 끝까지 모든 것을 삭제한다. 그래서 남은 문자열은 uid 형태를 가지게 되며, eval 명령은 명령라인을 평가하면서 root
    유저라면 uid=0을 실행하여 uid 로컬 변수에 0을 할당한다. 그리고 명령 변경자를 사용하여 uid 변수의 값이 0인지 테스트하고,
    아니면 then 이하의 echo 명령에서 첫 번째 위치 파라미터 $0의 값을 출력하게 되며, 0이면 else 다음의 echo 명령을 실행한다.
 
bash 옵션들
 
-쉘 호출 옵션: 싱글 캐릭터 옵션은 대시(-) 다음에 단일 문자가 오며, 멀티 캐릭터 옵션은 두 개의 대시(--) 다음에 여러 개의
  문자가 온다. 멀티 캐릭터 옵션은 싱글 캐릭터 옵션에 위치해야 한다. 일반적으로 인터렉티브한 로그인 쉘은 -i 옵션(인터렉티브
  쉘 시작), -s(표준 입력으로부터 읽기), -m(잡 컨트롤 가능) 옵션을 가지고 시작된다.
 
<쉘 호출 옵션>
옵션
의미
-C sring
-c 플래그가 있으면 문자열로부터 명령을 읽어들인다. 문자열 뒤에 전달인수가 있으면 그 전달인수는 $0부터 시작하여 위치 매개변수로 지정된다.
-D
$로 시작되고, 큰 따옴표로 인용된 문자열들의 목록은 표준 출력으로 출력된다. 현재 로케일이 C 또는 POSIX가 아닐 때 이 문자열들은 언어 번역을 위한 제목이다.
-i
-I 플래그가 있으면 쉘은 대화형(interactive) 모드로 동작한다.
-s
-s 플래그가 있을 때 또는 옵션 처리 후에 남은 인수가 없을 때에는 표준 입력으로부터 명령을 읽어들인다. 이 옵션을 사용하여 대화형 쉘을 실행시킬 때 위치 매개변수를 설정 할 수 있다.
-r
제한된 쉘을 시작한다.
-
--
옵션의 마지막 시그널이며 옵션 프로세싱을 더 이상 할 수 없다.
--또는 –옵션 이후의 아규먼트들은 파일명과 아규먼트로 취급한다.
--dump-strings
-D 옵션과 같다.
--help
빌트인 명령을 위한 사용법 메시지를 출력하고 종료한다.
--login
bash가 마치 로그인 쉘로 시작된 것처럼 행동하게 한다.
--noediting
bash가 대화형 모드로 실행 중일 때 readline 라이브러리를 사용하지 않는다.
--noprofile
시스템 전역 시동 파일인 /etc/profile 또는 ~/.bash_profile, ~/.bash_login, ~/.profile 파일과 같은 모든 개인 초기화 파일을 읽지 않도록 한다. bash가 로그인 쉘로 실행될 때에는 기본적으로 이 모든 파일을 읽는다.
--norc
쉘이 대화형 모드일 때 유저 개인의 초기화 파일인 ~/.bashrc 파일을 실행하지 않도록 한다. 쉘을 실행할 때 bash9sh)라는 이름으로 실행하면 기본적으로 이 옵션이 켜진다.
--posix
기본적으로 POSIX 1003.2 표준과 다른 BASH 행동 방식을 바꾸어 표준에 부합되도록 지시한다.
--quiet
쉘을 시작할 때 상세한 정보를 보여주지 않는다. 즉, 쉘 버전과 기타 정보를 표시하지 않는다. 기본값이다.
--rcfile file
쉘이 대화형 모드일 때 표준적인 개인 초기화 파일인 ~/.bashrc 대신 파일의 명령을 실행한다.
--restricted
제한된 쉘을 시작한다. –r 옵션과 같다.
--vervose
vervose 옵션을 켠다. –v 옵션과 같다.
--version
bash 쉘에 대한버전 정보를 표시하고 종료한다.
  
- set 명령과 옵션들: set -기호를 사용하여 옵션을 on하고 set +기호를 사용하여 off옵션을 설정 할 수 있다.
# set -f
# echo ??????
  ??????  -> 입력한 값을 그대로 출력
# set +f
# echo ??????
  f1.txt, f2.txt ....  -> .을 포함한 6자리의 파일명을 출력
 
<set 명령 옵션>
set 명령 옵션
짧은 옵션
의미
allexport
-a
설정을 해제할 때까지 뒤이어서 나올 명령의 환경으로 export하기 위해 수정 또는 생성할 변수를 자동으로 표기한다.
breacexpand
-B
브레이스 확장이 가능하며 기본값으로 설정되어 있다.
emacs
 
이맥스 스타일의 명령행 편집 이터페이스를 사용하며, 기본값으로 설정되어 있다.
errexit
-e
명령이 0 아닌 상태값을 갖고 종료하면 즉시 종료한다. 만약 실패한 명령이 until 또는 while 루프의 일부, if 문의 일부, &&의 일부, || 목록의 일부이거나 또는 명령의 반환값이 !로 반전되면 종료하지 않는다.
histexpand
-H
! 스타일의 히스토리 치환을 사용한다. 쉘이 대화형 모드이면 기본으로 켜지는 플래그이다.
ignoreeof
 
쉘을 빠져나오기 위해 <Ctrl-d>를 눌러 EOF하지 못하도록 한다. 이때에는 exit 명령을 사용해야 한다. 쉘 명령 ‘IGNOREEOF=10’을 실행한 것과 같은 효과를 발휘한다.
keyword
-k
명령을 위한 환경에서 키워드 아규먼트를 배치한다.
interactive-comments
 
인터렉티브 쉘에서 이 옵션을 사용하지 않으면 # 주석을 사용할 수 없다. 기본값으로 설정되어 있다.
monitor
-m
잡 컨트롤을 허용한다.
noclobber
-C
리다이렉션이 사용될 때 덮어쓰기로부터 파일을 보호한다.
noexec
-n
명령을 읽지만 실행하지 않으며, 스크립트의 문법을 체크하기 위해 사용된다. 인터렉티브로 실행했을 때에는 이 옵션이 적용되지 않는다.
noglob
-d
경로명 확장을 할 수 없다. 와일드카드가 적용되지 않는다.
notify
-b
백그라운드 잡이 종료되었을 때 유저에게 알려준다.
nounset
-u
변수 확장이 설정되지 않았을 때 에러를 출력해 준다.
onecmd
-t
하나의 명령을 읽고, 실행한 다음 종료한다.
physical
-P
이 옵션이 설정되면 cd 또는 pwd를 입력했을 때 심볼릭 링크는 가져오지 못한다. 물리적인 디렉터리만 보여준다.
posix
 
기본 연산이 POSIX 표준과 매칭되지 않으면 쉘의 행동이 변경된다.
privileged
-p
이 옵션이 설정되었을 때 쉘은 .profile 또는 ENV 파일을 읽지 않으며, 쉘 함수는 환경으로부터 상속되지 않는다.
verbose
-v
쉘에서 행 입력을 받을 때마다 그 입력행을 출력한다.
vi
 
명령라인 에디터로 vi 에디터를 사용한다.
xtrace
-x
각각의 간단한 명령을 확장한 다음, bash PS4의 확장값을 표시하고 명령과 확장된 인수를 표시한다.
 
bash 스크립트를 이용하여 Text GUI 만들기
  
-dialog 유틸리티 설치하기
# rpm -qa|grep dialog  -> 확인
# yum install dialog -y  -> 설치
 
-dialog 사용법 확인
# dialog --help  # man dialog
 
-메세지 박스
# dialog --title "메세지 박스" --backtitle "쉘 스크립트 프로그래밍" --msgbox "리눅스 쉘 스크립트" 15 30
 -> 타이틀과 백타이틀 설정, msgbox 높이는 15 너비는 30
 
-yes/no 박스
# vi ynbox.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
dialog --title "경고 : 파일 삭제" --backtitle \
"리눅스 프로그래밍" --yesno \
"\n삭제하시겠습니까? '/home/multi/testdel.sh' file" 7 60
sel=$?
case $sel in
     0) echo "삭제를 선택했습니다.";;
     1) echo "삭제를 선택하지 않았습니다.";;
     255) echo "<Esc>키를 눌러 취소하였습니다.";;
esac
----------------------------------------------------------------------------------
# chmod +x ynbox.sh
# ./ynbox.sh
 -> --yesno 옵션을 사용하여 yes/no 박스를 보여주고 sel 변수에 $? 값을 할당하여 선택 결과에 따라 다른 메세지를 출력
 
-입력 박스
# vi inputbox.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
dialog --title "입력 박스" --backtitle "쉘 스크립트 프로그래밍" --inputbox "이름을 입력하세요." 8 60 2>/tmp/input.$$
 
sel=$?
name=`cat /tmp/input.$$`
 
case $sel in
     0) echo "$name님 안녕하세요." ;;
     1) echo "취소를 누르셨네요." ;;
     255) echo "<Esc>키를 누르셨네요." ;;
esac
rm -f /tmp/input.$$
----------------------------------------------------------------------------------
# chmod +x inputbox.sh
# ./inputbox.sh
 -> --inputbox은 유저로부터 문자열을 입력받기 위해 사용하는 옵션이며, 3>/tmp/input.$$와 같이 입력한 값을 파일로 저장한다.
    여기서 $$는 현재 실행중인 쉘의 PID를 의미하며 sel 변수에 이전 명령의 종료 상태값($?)을 할당하였고, name 변수에 cat/tmp/
    /input.$$ 명령을 저장해두었으며, <Esc>키가 눌러지면 255) 항목의 명령을 실행하도록 하였다. 마지막으로 수행이 끝나면
    이전에 사용했던 파일은 rm -f를 이용하여 삭제하였다.
 
-라디오 리스트
# dialog --backtitle "라디오 리스트" --radiolist " 선택하세요" 15 25 3 1 "one" "off" 2 "two" "on" 3 "three" "off"
 -> --radiolist를 사용하여 체크 박스를 1, 2, 3번의 체크 리스트를 만들고 2번의 on 상태를 기본으로 유지
  
-dialog 예제 만들어 보기
# touch dialogbox.sh
# chmod +x dialogbox.sh
# vi dialogbox.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
dialog --title "vsftpd 서버 관리" --backtitle "vsftpd 서버 관리" \
--msgbox "vsftpd 서버를 관리합니다. " 15 35
dialog --title "vsftpd 시작/중지/재시작" --backtitle "vsftpd 시작/중지/재시작" \
--menu "선택하세요." 15 35 4 start "시작하기" stop "중지하기" \  # 높이15 너비35, 메뉴높이4
restart "재시작하기" exit "종료" 2>/tmp/vsftpd_menu.$$  # restart를 /tmp 디렉터리 아래 vsftpd_menu.[PID]형태로 리다이렉션
 
menuitem=`cat /tmp/vsftpd_menu.$$`
 
case "$menuitem" in
 
     start)
          /etc/rc.d/init.d/vsftpd start
          dialog --backtitle "결과" --infobox "vsftpd 서버를 시작하였습니다. " 10 25
          ;;
     stop)
          /etc/rc.d/init.d/vsftpd stop
          dialog --backtitle "결과" --infobox "vsftpd 서버를 중지하였습니다. " 10 25
          ;;
     restart)
          /etc/rc.d/init.d/vsftpd restart
          dialog --backtitle "결과" --infobox "vsftpd 서버를 재시작하였습니다." 10 25
          ;;
     exit)
          exit 0
          ;;
esac
rm -f /tmp/vsftpd_menu.$$
----------------------------------------------------------------------------------
 
# vi vsftpd_menu.sh
----------------------------------------------------------------------------------
#!/bin/bash
 
while :
do
     #clear
     echo "---------------------------------"
     echo "vsftpd 시작/중지/재시작"
     echo "---------------------------------"
     echo "[1] vsftpd 시작하기"
     echo "[2] vsftpd 중지하기"
     echo "[3] vsftpd 재시작하기"
     echo "[4] 프로그램 종료하기"
     echo "===================="
   echo -n "메뉴에서 번호를 선택하세요. [1-4] : "
     read choice
     case $choice in
          1) /etc/rc.d/init.d/vsftpd start \
               && ps ax|grep /usr/sbin/vsftpd|grep -v grep;;
          2) /etc/rc.d/init.d/vsftpd stop;;
          3) /etc/rc.d/init.d/vsftpd restart \
          4) exit 0;;
          *) echo "1에서 4번 중 선택하세요.";;
     esac
done
----------------------------------------------------------------------------------
# chmod  +x vsftpd_menu.sh
# ./vsftpd_menu.sh
 
유용한 유틸리티
 
<실습 설정>
# vi sname(공백은 tab으로 구분)
----------------------------------------------------------------------------------
11     사과
12     배
13     복숭아
14     참외
15     수박
----------------------------------------------------------------------------------
 
# vi sprice(공백은 tab으로 구분)
----------------------------------------------------------------------------------
11     300
12     500
13     200
14     150
15     5000
----------------------------------------------------------------------------------
 
-cut 명령: 파일에서 지정한 각 라인의 필드를 자르는 명령
<형식>
cut -f[필드번호] [파일명]
# cut -f2 sname
 -> 2열만 잘라서 출력
# cut -f1 sname
 -> 1열만 잘라서 출력
 
-paste 명령: 텍스트 정보를 합치는 명령
<형식>
paste [파일1] [파일2]
# paste sname sprice
 
-join 명령: 두 파일에서 같은 값을 가지는 필드는 합치고 나머지 필드는 더하는 명령
<형식>
join [파일1] [파일2]
# join sname sprice
 
-tr 명령: 표준 입력으로부터 문자들을 변경하거나 삭제하고 표준 출력으로 출력
<형식>
tr [패턴1] [패턴2]
# tr "12" "xy" < sname
 -> 1 문자를 x로, 2 문자를 y로 변경하는 명령
# tr "[a-z]" "[A-Z]"
 -> 소문자를 대문자로 변경
 
-uniq 명령: 인접한 라인의 같은 문자열을 검색하여 되풀이 되는 라인은 한 개의 문자열만 제외하고 모두 삭제
<형식>
uniq [파일명]
 
# vi pname
----------------------------------------------------------------------------------
리눅스 좋아하세요?
CentOS
CentOS
환영합니다.
리눅스의 세계로 오신 것을 환영합니다.
리눅스를 좋아하세요?
페도라
페도라
----------------------------------------------------------------------------------
# uniq pname
 -> 중복된 CentOS와 페도라는 한 개만 남기고 모두 삭제
# sort pname | uniq
 -> sort 명령을 활용하면 인접해 있지 않은 같은 내용에 대해서도 삭제할 수 있다.
 
-split 명령: 용량이 큰 텍스트 파일을 크기 단위 또는 라인 단위로 잘라낼 수 있다.
# split --help  -> 옵션 확인...(unix와 옵션이 다름)
# split -l [라인수] [파일명] [저장할 파일명(안써도됨)] -> 라인 수로 데이터 나누기(나누었을 때 알파벳(aa..ab)을 기준으로 분류)
# split -b [바이트 수] -d [파일명] [저장할 파일명(안써도됨)] -> 데이터의 크기로 데이터 나누기(-d 옵션을 사용하여 숫자로 채움)
 
-col 명령: "\n\r" 문자를 "\n" 문자로, 공백문자를 탭문자로, 백스페이스 삭제 문자로 변경하는 필터이다.
# man col  -> 옵션 확인
col 옵션
의미
-b
어떠한 백스페이스 문자도 출력하지 않는다. 백스페이스 문자와 연결되는 마지막 문자만 출력한다.
-f
밑줄 속성을 가진 문자열을(Forward half line feed) 변환하지 않는다. 일반적으로 밑줄 속성을 가진 문자열들은 다음 라인에서 밑줄이 나타난다.
-h
여러 공백문자를 탭문자로 바꾼다.
-x
여러 공백문자들을 그대로 둔다.
-l[num]
메모리에 한 번에 둘 수 있는 최대 라인수를 num 라인수로 한다.
초기값은 128라인이다.
  
-xargs 명령 :입력된 데이터를 라인 단위로 읽어서 아규먼트화하는 명령이다.
# xarg --help -> 옵션 확인
# which bash | xargs ls -l
 -> which bash 명령의 결과값을 변수로 하여 ls -l 실행. 즉 ls -l 'which bash' 와 같음.
 
-find 명령: 디렉터리 계층에서 파일과 디렉터리를 검색한다.
<find 옵션>
find옵션
의미
-name 파일명
파일명으로 검색한다.
-user 유저명
유저명 또는 UID로 검색한다.
-group 그룹명
그룹명으로 검색한다.
-perm nnn
퍼미션이 nnn인 파일을 검색한다.(예 –perm 755)
# find. –perm -100 –print
실행 가능한 –x-----파일을 찾는다.
-perm 인자가 마이너스(-) 부호를 가지게 되면 setuid 설정 비트를 포함한 모든 퍼미션 비트들이 검사된다.
-type x
파일 타입이 x인 파일을 검색한다.
b(블록 특수 파일), c(문자 특수 파일), d(디렉터리), p(파이프), f(정규표현 일반 파일), l(심볼릭 링크 파일), s(소켓)
-atime +n
접근 시간이 n일 이전인 파일을 검색한다. (access)
-atime –n
접근 시간이 n일 이내인 파일을 검색한다. (access)
-ctime +n
n일 이전에 변경된 파일을 검색한다.
(change: 내용 수정이 아니라 모드 변경 또는 접근 시간 변경)
-ctime -n
n일 이내에 변경된 파일을 검색한다.
(change: 내용 수정이 아니라 모드 변경 또는 접근 시간 변경)
-mtime +n
n일 이전에 내용이 수정된 파일을 검색한다. (modify)
-mtime –n
n일 이내에 내용이 수정된 파일을 검색한다. (modify)
-empty
파일명이 비어있고(0 bytes) 일반 파일이거나 디렉터리를 검색한다.
-newer 파일명
파일명의 파일보다 최근에 수정된 파일을 검색한다.
-size n
파일 블록 크기가 n 이상인 파일을 검색한다.
b(블록-기본값), c(bytes), k(kbytes), w(2바이트 단어)
-links n
링크된 개수가 n인 파일을 검색한다.
-print
표준 출력
-exec 명령
검색된 파일을 찾으면 COMMAND 명령을 실행한다.
명령 인자(검색된 파일)는 {}으로 사용하며, 이때 명령 끝은 \;을 사용해야 한다. 즉, 명령구분 문자인 ‘;’을 탈출(\)시켜 주어야 한다.
operator
-a: and 연산, -o: or 연산, !: not 연산
-path 패턴
path가 패턴과 일치하는 path에 대해서 검색한다.
-regex 패턴
파일명이 패턴과 일치하는 정규표현식에 대하여 검색한다.
# find . -type f -exec file '{]' \;  -> 현재 디렉토리에서 모든 파일을 검색하여 file 명령을 실행
# find $HOME mtime 0  -> 자신의 홈 디렉토리 아래에 24시간 안에 수정된 파일들을 검색하여 출력
# find . -name 'fi*'  -> 현재 디렉터리부터 모든 하위 디렉터리까지 fi로 시작하는 모든 파일을 검색하여 출력
# find . -perm 755  -> 현재 디렉터리부터 모든 하위 데렉터리까지 퍼미션이 755인 파일과 디렉터리를 검색
# find /home -newer here.sh  -> /home 디렉터리 아래에서 here.sh 파일보다 최근에 수정된 파일을 검색하여 출력
# find /home -size + 1024 -print  -> /home 디렉터리 아래에서 파일의 블록 크기가 1024 이상인 파일을 검색하여 출력
# find -linux -type d -print  -> lunux 계정의 홈디렉터리(/home/linux) 아래에서 디렉터리들만 검색하여 출력
# find /home \( -name a.out -o -name '*.0' \) -atime +7 -exec rm '{}' \;
 -> /home 디렉터리 아래에서 파일명이 a.out 또는 .o로 끝나는 파일을 검색하고, 7일 동안 사용하지 않는 파일이면 rm명령을
    사용하여 삭제
# find /tmp -name core -type f -print | xargs /bin/rm -f
 -> /tmp 디렉터리 아래에서 파일명이 core 파일을 검색하고 삭제한다.
# find . - type f -mtime +1 | xargs -n 100 rm -f
 -> 현재 디렉터리 아래에 1일전에 작성/변경된 파일을 찾아 아규먼트로 치환하고 rm-f 로 100개 단위로 검색된 파일들을 삭제
 
-tee 명령: 표준 입력으로부터 읽어서 파일로 저장하고 출력하는 명령
<tee 명령 옵션>
tee 옵션
의미
-a, --append
덮어쓰지 않고 주어진 파일에 표준 입력을 추가한다.
--help
표준 출력으로 사용법을 출력하고 정상적으로 종료한다.
-I, --ignore-interrupts
인터럽트 신호를 무시한다.
--version
표준 출력으로 버전 정보를 출력하고 정상적으로 종료한다.  
# cat/ etc/passwd | grep fedora | tee fedora.txt  -> 명령을 출력하면서 fedora.txt로 저장
# cat fedora.txt
# cat /etc/passwd | grep root | tee -a mulit.txt  -> 명령을 출력하면서 multi.txt로 저장
# cat multi.txt
 
<yum 사용법>
1. 업데이트 목록 보기
     # yum list updates
2. 업데이트 목록을 다운로드하고, 즉시 업데이트를 설치 
     # yum update -y
3. 설치된 rpm 패키지 목록 보기 
     # rpm -qa
     # yum list installed
4. gcc 패키지가 설치되어 있는지 확인
     # rpm -qa | grep gcc
     # yum list installed gcc
5. gcc 패키지를 설치?
     # yum install gcc gcc-c++
6. gcc를 패키지 업데이트
     # yum update gcc gcc-c++
7. 패키지 이름으로 검색
     # yum list 패키지명
     # yum list 정규식
     # yum list gcc
     # yum list gcc*
8. 여러개의 패키지 설치
    # yum install gcc gcc-c++
9. 패키지 삭제
    # yum remove gcc gcc-c++
10 설치가 가능한 모든 패키지 확인
     # yum list all
11. 패키지 그룹보기
     # yum grouplist
12. 패키지 그룹 모두 설치
     # yum groupinstall "Development Tools"
13. 그룹 패키지를 업데이트하려면?
     # yum groupupdate "Development Tools"
14. 그룹패키지를 삭제
     # yum groupremove :Development Tools"
15. 아키텍처를 지정하여 설치
     # yum install mysql.i386
16. 파일을 가지고 있는 패키지명 확인
     # rpm -qf /etc/passwd
     # yum whatprovides /etc/passwd
17. 맨페이지 보기
     # man yumJ
18. yum fastestmirror 패키지를 설치하면 yum 미러 서버 중 속도가 가장 빠른 서버를 자동으로 찾아서 연결해 준다.
     # yum install yum-fastestmirror -y

'IT기술노트 > Linux' 카테고리의 다른 글

fail2ban을 이용한 SSH 접속 IP 차단 방법  (1) 2024.11.07

+ Recent posts