프로그래밍을 하다 보면, 특히나 리눅스 환경에서 프로그래밍을 하다 보면 쉘 스크립트(Shell script)라는 단어를 들을 일이 있는데, 비슷한 단어인 쉘 코드(shell code)라는 단어와 햇갈릴 수 있습니다.

 

이 두 용어는 확실히 다른 단어로 혼용하시면 안됩니다.

 

간단하게 말하자면

 

쉘 스크립트쉘에서 사용되는 명령어를 나열한 실행가능한 텍스트파일이며,

쉘 코드쉘을 실행시키는 코드입니다.

 

실제 제가 사용하는 쉘 스크립트를 예를 들어 설명해보도록 하겠습니다.

 

리눅스 시스템에는 가장 범용적인 커멘드라인 쉘인 bash가 있습니다.

사용자는 이 bash 쉘에 명령어를 입력해서 무언가 하고싶은 동작들을 할 수 있습니다.

 

이 리눅스의 사용자인 저는, 리눅스 환경에서 알고리즘 문제를 풀려고, 문제별로 디렉토리와 소스코드 파일, 및 입력 테스트 케이스 파일들을 생성해서 잘 정리해 놓습니다.

 

그런데 매 문제를 만들 때 마다 디렉토리 구조를 만들고, 하는 것들이 항상 번거로워서 이를 자동화 하려고 합니다.

 

따라서 쉘 스크립트 파일 mk.sh 를 만들고, 이를 이용해서 디렉토리를 쉽게 만들려고 합니다.

 

아래에 첨부된 쉘 스크립트에 실행 권한을 준 뒤 다음 명령어를 입력하면 디렉토리가 생성됩니다.

 

./mk.sh dir main.cpp 3

위와 같이 인자를 주게 되면 다음과 같은 디렉토리 구조가 생성되게 됩니다.

> dir
-----> bin
-----> src
----------> main.cpp
-----> input1.txt
-----> input2.txt
-----> input3.txt

쉘 스크립트의 첫번째 인자는 문제 이름을 나타내는 디렉토리 명이며, 두번째 인자는 소스코드의 명입니다. 세번째 인자는 input.txt 파일의 개수가 됩니다.

 

mk.sh 쉘 스크립트의 내용은 다음과 같습니다.

#!/bin/bash

dir_path=$1
src_fname=$2
num_args=$#


if [ "$num_args" -ge 2 ]; then
    echo "mkdir -p `pwd`/$dir_path/src"
    mkdir -p `pwd`/$dir_path/src
    echo "touch `pwd`/$dir_path/src/$src_fname"
    if [ `echo $src_fname | cut -d"." -f2` == "cpp" ]; then
        echo -e "#include <bits/stdc++.h>\nusing namespace std;\n\nint main() {\n\treturn 0;\n}\n" > `pwd`/$dir_path/src/$src_fname
    else
        touch `pwd`/$dir_path/src/$src_fname
    fi
    if [ "$num_args" -eq 3 ]; then
        num_input=$3
        
        i=1
        while [ $i -le $num_input ]
        do
            echo "touch `pwd`/$dir_path/input.$i.txt"
            touch `pwd`/$dir_path/input.$i.txt
            i=`expr $i + 1`
        done

    else
        echo "touch `pwd`/$dir_path/input.1.txt"
        touch `pwd`/$dir_path/input.1.txt    
    fi

else
    echo "Usage: $0 [directory path] [source file name with extension] (number of input file. optional)"
    echo "Supported file extension: cpp, py, asm"
    echo "사용법: $0 [디렉토리 경로] [확장자 포함 소스파일 이름] (입력 파일 개수. 옵션)"
    echo "지원하는 확장자: cpp, py, asm"
    

fi

 

위와 같이 쉘 스크립트를 텍스트 파일로 작성한 뒤, 실행을 하면 스크립트 안에 있는 내용들이 bash 쉘에서 순차적으로 실행되어 결과를 내게 됩니다.

 

이와 같이 쉘 스크립트쉘에서 동작하는 명령어들을 한꺼번에 텍스트 파일로 모아서, 여러번 사용가능하게 만들어 놓은 것이 쉘 스크립트입니다.

 

 

이와는 다르게 쉘 코드쉘을 실행시키는 코드입니다.

 

가령 Python으로 작성을 한다면 다음과 같은 코드가 쉘 코드가 되겠죠

import os

os.system("/bin/bash")

아니면 다음과 같은 방식으로도 생성할 수 있습니다.

쉘 코드 생성을 처음 공부할 때에는 많이 사용하는 방법 중 하나입니다.

 

다음과 같은 C언어 코드를 작성합니다.

#include <stdlib.h>
int main()
{
	char *str[2];
	str[0] = "/bin/bash";
	str[1] = 0;	
	execve(str[0], str, 0);
}

 

위 녀석을 컴파일하여 기계어로 만든 뒤, 독립적으로 실행되어도 쉘이 떨어지도록 정제를 합니다.

이 부분에 디테일한 부분은 생략하도록 하고, 좀더 내용을 보고싶으면 참고한 해커스쿨 쉘코드 강좌 링크를 눌러보세요.

 

오래된 자료라서 지금과는 많이 환경이 맞지 않는 부분이 있을 수는 있으나, 개념적인 부분은 도움이 많이 될 것입니다.

 

과정은 생략하고, 결과적으로는 

\xeb\x15\x31\xc0\x5b\x89\x43\x07\x89\x1e\x89\x46\x04\xb0\x0b\x31\xe4\x8d\x0e \x31\xd2\xcd\x80\xe8\xe6\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68

와 같은 기계어 코드를 얻을 수 있습니다.

 

이 기계어 코드가 CPU에서 실행되면, 쉘이 나타나게 되는 것이죠. 저러한 코드를 쉘 코드라고 부릅니다.

 

요 녀석은 일반적인 개발에서는 사용할 일이 거의 없는데, 해킹을 할 때에는 필수적인 녀석 중 하나입니다.

 

해커들이 보통 하는짓들이 프로그램의 취약점을 찾아내서, 의도치 않은 쉘을 띄우게 하는 것이기 때문이죠. 이 때, 쉘을 띄우게 하기 위해서 저 쉘코드를 주입한 뒤, 프로그램 카운터를 쉘코드의 시작 주소로 이동시켜서 쉘을 실행시킵니다.

 

아무쪼록 쉘코드와 쉘스크립트의 차이점에 대해 잘 이해가 되었기를 기원하며 이만 글을 줄입니다.

본 문서는 다음 링크의 문서를 번역한 것입니다.

https://docs.microsoft.com/ko-kr/windows-hardware/drivers/print/print-spooler-architecture


틀린 번역이나 어색한 표현이 있을 수 있습니다.


[번역]

프린트 스풀러 아키텍쳐


윈도우 2000버전과 그 이후버전의 프린터 스풀러는 마이크로 소프트가 제공한 것과, 밴저가 제공한 컴포넌트들로 이루어져 있습니다.

이 스풀러들은 다음 역할들을 수행합니다.


- 프린트 업무가 로컬로 처리되어야 하는지, 네트워크를 넘어서 처리되어야 하는지


- 프린터 드라이버와 함께 GDI로 부터 생성된 데이터 스트림을 받아들여서, 특정 타입의 프린터에서 출력하도록 한다.


- 스풀링이 활성화 되어 있다면, 데이터를 파일로 스풀링한다.


- 논리 프린터 큐에서 첫번째로 가용한 물리적 프린터를 고른다.


- 스풀된 포맷(EMF 와 같은)의 데이터 스트림을 프린터 하드웨어로 보낼 수 있는 데이터 형식(PCL와 같은) 형식으로 변환한다.


- 데이터 스트림을 프린터 하드웨어로 보낸다.


- 스풀러 컴포넌트와 프린터 폼을 위한 레지스트리 기반 데이터베이스를 관리한다.


- (윈도우 비스타의 경우) 프린터 서버에서 하는 것 대신, 클라이언트 컴퓨터에서 프린팅 작업을 한다. 클라이언트 사이드 랜더링은 프린터 서버의 업무 량을 줄여주고,

윈도우 비스타에서는 이 기능이 기본값으로 활성화 되어 있다.


- 윈도우 7에서 프린터 드라이버는 스풀러가 구동되는 프로세스와 다른 프로세스에서 별개로 구동 될 수 있다. 이 기능은 Printer Driver Isolation(프린터 드라이버 고립)이라고 불린다.




[원문]



Print Spooler Architecture

The Microsoft Windows 2000 and later print spooler is made up of a set of Microsoft-supplied and optional vendor-supplied components, with responsibilities that include:

  • Determining whether a print job should be handled locally or across a network.

  • Accepting a data stream created by GDI, in conjunction with a printer driver, for output on a particular type of printer.

  • Spooling the data to a file (if spooling is enabled).

  • Selecting the first available physical printer in a logical printer queue.

  • Converting a data stream from a spooled format (such as enhanced metafile (EMF)) to a format that can be sent to printer hardware (such as printer control language (PCL)).

  • Sending a data stream to printer hardware.

  • Maintaining a registry-based database for spooler components and printer forms.

  • (Windows Vista) Rendering print jobs on the client computer instead of on the print server. Client-side rendering eases the print server workload, is transparent to the print driver, and is enabled by default in Windows Vista.

  • For Windows 7, print drivers can run in a separate process from the spooler. This feature is called Printer Driver Isolation.


본 문서는 다음 링크의 문서를 번역한 것입니다.

https://docs.microsoft.com/ko-kr/windows-hardware/drivers/print/introduction-to-printing


틀린 번역이나 어색한 표현이 있을 수 있습니다.


[번역글]

프린팅 관련 설명


마이크로소프트 윈도우 프린팅 아키텍쳐는 프린트 스풀러와 프린터 드라이버들로 이루어져 있습니다.

어플리케이션은 장치의 종류와 상관없이 함수를 호출함으로서, 프린팅 잡을 만들고 그 잡을 다양한 장비로 보냅니다.

그 다양한 장비는 레이저 프린터가 될수도, 벡터 플로터가 될수도, 래스터 프린터가 될수도 있고 팩스 장비가 될 수도 있습니다.


프린터 드라이버에는 랜더링 컴포넌트와 설정 컴포넌트가 있습니다. 

랜더링 컴포넌트는 어플리케이션이 제공한 그래픽 명령어를 프린터가 이미지를 페이지에 그리는데 사용하는

데이터 포맷으로 변환시킵니다.

설정 컴포넌트는 유저 인터페이스 컴포넌트와 프로그램 인터페이스 컴포넌트가 있습니다.

유저 인터페이스 컴포넌트는 유저가 프린터에서 설정가능한 옵션들을 보여주고, 프로그램 인터페이스는 프린터의 설정값과 특징들을 어플리케이션과 소통하도록

해줍니다.


마이크로소프트    win32 gdi 어플리케이션이 프린트 할 때, 이 앱은   win32 api의 gdi 함수를 호출합니다. 이러한 함수들은  gdi 그래픽 엔진에 정보를 전달합니다.

GDI 그래픽 엔진은 그리는 명령어들을 EMF(enhanced metafile)로 스풀하거나, 프린터 드라이버와 함께 스풀러로 보낼 수 있는 프린팅 할 수 있는 이미지를 그립니다.

스풀러 컴포넌트는 EMF 파일을 해석해서, 페이지 레이아웃 정보와 작업 제어 명령을 데이터 스트림으로 변환합니다.

스풀러는 그때, 데이터 스트림을 직렬, 병렬 혹은 네트워크를 통해 관련된 타겟 프린터의 입출력 포트로 보냅니다. 게다가, XPS 장비에서 출력하면, GDI 프린트 명령어는 GDI 에서 XPS로 변환하는 컴포넌트를 통해 변환되어, 프린트 업무는 XPS 프린트 경로로 보내집니다.

XPS 프린트 경로에서는, 프린터 장비는 XPS(XML Paper Specification)을 기반으로 이루어집니다. 마이크로소프트 Win32 XPS 앱이 프린트하면, 앱은 XPS 프린트 API에 있는 XPS 함수를 호출합니다.

XPSDrv 프린터 드라이버와 함께 프린트를 하면, 스풀러는 XPS 스풀 파일을 곧바로 장비로 보내서 랜더링하고 출력하도록 합니다. XPS 파일이 GDI 장비에서 출력될때, EMF 파일은 XPS 에서 GDI로 변환하는 모듈을 통해 변환됩니다. 그러면 그때, GDI 프린트 경로로 보내지며 Win32 GDI 앱과 비슷한 방식으로 동작합니다.


WPF(Windows Presentation Foundation) 앱은 WPF 프린트 지원 함수를 호출해서 XPS 문서가 XPS 스풀 파일 포맷을 스풀러가 처리하도록 합니다. Win32 XPS 앱에서 프린팅을 할 때처럼, 스풀러가 XPSDrv 프린터 드라이버로 프린트 할 때, 스풀러는 스풀된 파일을 원본 형식으로 보내서 XPSDrv 프린터 드라이버가 프린터에서 출력하도록 합니다.스풀러가 GDI 기반을 가진 버전 3의 프린터 드라이버로 프린터 할때, 스풀러는 데이터를 XPS 스풀 파일 포맷을 EMF파일에서 GDI로 변환하는 모듈로 보냅니다.

그때 프린터를 하기 위해서 GDI 기반의 프린터로 데이터를 보냅니다. 데이터 경로에 대하여 더 많은 정보를 보기 위해서는 Windows Print Path Overview를 확인하세요.

XPS 에 대한 더 많은 정보를 확인하기 위해서는 XML Paper Specification Overview에 대하여 확인하세요.


스풀러와 드라이버 컴포넌트는 대체가능하며, 따라서 하드웨어 제조사는 쉽게 새 하드웨어에 대한 지원을 추가할 수 있습니다. 스풀러와 드라이버 컴포넌트에 대하여 더 많은 정보를 원한다면 다음 내용들을 참고하세요.


Print Spooler Architecture

Printer Driver Architecture


새로운 프린터를 사용하는 것은 일반적으로 새 데이터 파일을 만들어서 MS 지원 프린터 드라이버를 설치하는 것 만으로도 가능합니다.

MS 프린터 드라이버에 대한 더 많은 정보를 보시려면 Printer Driver Overview를 확인하세요.


마이크로소프트 범용 프린터 드라이버와 마이크로소프트 Postscript 프린터 드라이버의 동작을 커스터마이징 가능합니다. 더 많은 정보를 위해서는, Customizing Microsoft's Printer Drivers를 보세요. 프린터 스풀러도 커스터마이징이 가능합니다. 관련 정보는 Customizing Print Spooler Components를 확인하세요.


[원문]


Introduction to Printing

The Microsoft Windows printing architecture consists of a print spooler and a set of printer drivers. By calling device-independent functions, applications can create print jobs and send them to many devices. This includes laser printers, vector plotters, raster printers, and fax machines.

Printer drivers include a rendering component and a configuration component. The rendering component converts the graphics commands from the application into a data format that the printer uses to render the image on the page. The configuration component contains a user interface component that enables users to control a printer's selectable options and a program interface that communicates the printer's configuration and features to an application.

When a Microsoft Win32 GDI application prints, it calls GDI functions in the Win32 API. These functions pass the information to the GDI graphics engine. The GDI graphics engine either spools the drawing instructions as an enhanced metafile (EMF) file or, together with a printer driver, renders a printable image that can be sent to the spooler. Spooler components interpret EMF files, and they can insert page layout information and job control instructions into the data stream. The spooler then sends the data stream to the serial, parallel, or network port driver associated with the target printer's I/O port. In addition, if printing to an XPS device, the GDI print commands are converted through the GDI to XPS conversion component, and the print job is sent down the XPS print path.

In the XPS print path, printer drivers are based on the XML Paper Specification (XPS). When a Microsoft Win32 XPS application prints, the application calls XPS functions in the XPS Print API. When it prints to queues with XPSDrv printer drivers, the spooler passes the XPS spool file straight to the device for rendering and output. When the XPS file is printed to a GDI device, it is converted to an EMF file through the XPS to GDI Conversion Module. It is then sent through the GDI print path in a manner similar to Win32 GDI applications.

Windows Presentation Foundation (WPF) applications call WPF print support functions to spool XPS documents to the spooler in the XPS spool file format. As when printing from Win32 XPS applications, when the spooler prints to print queues with XPSDrv printer drivers, the spooler passes the spooled file in its original format to the XPSDrv printer driver for rendering and output to the printer. When the spooler prints to printers that have GDI-based, version 3 printer drivers, the spooler sends the data in the XPS spool file format to the GDI Conversion Module for conversion to an EMF file. It then sends the data to the GDI-based printer driver for printing. For more information about these data paths, see Windows Print Path Overview. For more information about XPS, see the XML Paper Specification Overview.

Spooler and driver components are replaceable, so hardware vendors can easily add support for new hardware. For more information about print spooler and driver components, see the following sections:

Print Spooler Architecture

Printer Driver Architecture

Support for a new printer usually requires only creating new data files for use with one of the Microsoft-supplied printer drivers. For more information about Microsoft printer drivers, see Printer Driver Overview.

You can customize the behavior of the Microsoft Universal Printer Driver and the Microsoft Postscript Printer Driver. For more information, see Customizing Microsoft's Printer Drivers. You can also customize the print spooler. For more information, see Customizing Print Spooler Components.

Other sections cover the following topics:

Terminal Server Printing

USB Printing

Bluetooth Printing

Printer Driver Testing and Debugging


사용방법

일본어를 한글로 소리나는 대로 입력하면 그에 맞는 히라가나가 나타납니다. 
촉음っ는 ㅅ만 입력하면 되며, ん는 ㅇ만 입력하면 됩니다. 요음 ゃゅょ는 각각 やゆよ를 입력한 뒤 _를 같이 입력하면 됩니다. 즉, ゃ는 야_ 라고 입력하면 되며 ゅ와 ょ는 각각 유_ 요_ 라고 입력하면 됩니다. を는 お와 차이를 두기 위해 오_라고 입력하면 됩니다. じ는 지라고 입력하면 되고 ぢ는 지_라고 입력하면 됩니다. ず는 즈라고 입력하고, づ는 즈_라고 입력하면 됩니다.

 불편한 기능은 점진적으로 업데이트 할 예정입니다. 추가 기능에 대한 의견 있으면 댓글 등으로 의견 남겨주시면 반영하도록 하겠습니다.

 

한글 입력

 


일본어 출력




리눅스에서 부팅 시 특정 작업을 하거나 특정 프로그램이 돌도록 하고 싶을 때가 있다. 그럴 경우 어떻게 해야하는지 차근차근 알아보자. 

본 포스팅은 우분투 16.04 기준으로 작성되었다. 하지만 다른 리눅스 배포판도 비슷한 구조를 가지고 있을 것이다.


리눅스 부팅 과정

일단 리눅스 부팅 과정을 간략하게 알아보자.


BIOS

메인보드에 있는 BIOS라고 불리는 펌웨어가 컴퓨터 부팅 시 필요한 처음 동작들을 처리한다. 이 BIOS는 POST(Power On Self Test)라고 불리는 동작을 통해서 부팅에 필요한 하드웨어들이 잘 연결되어 있는지, 하드웨어들이 잘 동작하는지 등을 확인한다. 그리고 부트 가능한 장치들을 사전에 설정된 부팅 우선순위(Periperial Booting Priority)에 따라 차례대로 각각의 장치의 MBR(Master Boot Record) 혹은 부트섹터라고 불리는 첫번째 섹터의 마지막 2바이트를 확인해서 부트섹터의 시그니쳐가 맞는지 확인한 후 시그니쳐(0x55AA)가 맞을 경우 해당 장치로 부팅을 시도한다. 그리고 MBR의 첫번째 바이트로 점프해서 기계어 Instruction을 실행한다.
최근에는 구식의 BIOS를 대체한 UEFI라는 녀석이 여기에 위치하는 경우도 있다.

MBR

부팅하도록 설정된 장치의 첫번째 섹터를 MBR(Master Boot Record)라고 하며, 여기에 나머지 부팅 절차들을 밟기 위한 명령어들이 있다. 하드웨어에서 한 섹터는 512바이트이며, 컴퓨터들은 하위 호환성을 유지하면서 발전했기 때문에, 저장장치의 용량이 커져도 이는 동일하다. 이 MBR에 있는 코드에는 리눅스 부트로더인 GRUB(혹은 레가시 시스템에서는 LILO)이 들어있다.

GRUB

GRUB은 Grand Unified Bootloader의 약자이며, MBR에 GRUB의 기계어 Instruction들이 있다. 하나의 저장장치에 여러개의 OS가 설치되어 있을 수 있으므로, GRUB은 어떤 OS로 부팅을 할 것인지 사용자가 설정할 수 있도록 UI를 제공한다. 사용자가 원하는 OS를 선택하면, 이 부트로더는 저장장치의 다른 섹터에 있는 커널 코드들을 메모리에 로드한 뒤, 커널 코드로 점프하여 커널의 기계어 Instruction들을 실행하도록 한다.

커널

드디어 리눅스 운영체제의 핵심부인 커널이 메모리에 올라오게 되었고, 이제 커널은 부팅을 마무리 짓기 위한 마무리를 지어야 한다.  grub 설정파일에 정의된 루트 경로에 부분에 루트 파일시스템을 마운트하고, /sbin/init 프로그램을 실행한다. init 프로세스는 해당 OS에서 실행된 첫번째 프로세스로 pid가 1이다. 우분투 최신 버전의 경우 init 프로세스 대신 systemd이라는 시스템 데몬 프로세스가 그 자리를 대신하기도 한다. 하지만 전체적인 맥락은 비슷하다.


Init

Init 프로세스는 해당 시스템에 저장된 런 레벨에 맞게 동작한다. 런 레벨은 보통 0부터 6까지의 숫자로 이루어져 있으며 시스템을 어떤 방식으로 부팅하는지를 결정한다. systemd로 제어되는 시스템의 경우 더 많은 종류의 런 레벨을 갖고 있으며, 리눅스 메뉴얼 페이지에서 man systemd.special명령어로 확인이 가능하다.


0 - 시스템 종료


1 - 싱글 유저 모드.

 계정이 하나만 존재한다. 시스템 복원모드라고도 불리며, 기본적으로 관리자 권한의 쉘을 얻게 된다. 파일시스템을 점검하거나 관리자 암호 변경 시 사용한다. S 모드와의 차이점은, 이 모드는 멀티 유저 모드에서 싱글 유저 모드로 스위치 된 경우 이 모드이다. 점검을 위해 싱글 유저 모드로 들어간 경우라고 인식된다.

S - 싱글 유저 모드

1번 모드와 동일하나, 부팅 시 부터 싱글 유저 모드 인 경우이다.

2 - 멀티유저모드, NFS비활성화. 

여러개의 계정을 사용할 수 있으며, NFS(Network File System)사용이 불가능하다. 3번 모드와 같지만 네트워크 사용이 불가능하다.

3 - 풀 멀티유저 모드.

CLI를 가지며 멀티 유저를 지원한다.

4 - 사용안함. 

기본적으료 사용하지 않는 모드이며, 사용자 정의하여 원하는 모드로 사용 가능하다.

5 - X11

3번 모드와 같이 멀티 유저를 지원하는 일반모드이지만 GUI를 지원한다는게 큰 차이점이다.

6 - 재시작

시스템을 재시작한다.


런레벨 프로그램

Init 프로세스가 런 레벨을 결정하면, 각각의 런 레벨에 맞는 서비스들을 실행해야 한다. 이때 각각 런 레벨 별 실행해야하는 서비스들의 디렉토리 경로는 다음과 같다.

레벨 S - /etc/rcS.d
레벨 0 - /etc/rc0.d
레벨 1 - /etc/rc1.d
레벨 2 - /etc/rc2.d
레벨 3 - /etc/rc3.d
레벨 4 - /etc/rc4.d
레벨 5 - /etc/rc5.d
레벨 6 - /etc/rc6.d

여기서 rc는 Run Command의 약자라고 한다.

/etc/rc0.d 디렉토리를 보면 다음과 같이 보인다.
 

root@ubuntu:/etc# tree rc1.d/
rc1.d/
├── K01alsa-utils -> ../init.d/alsa-utils
├── K01bluetooth -> ../init.d/bluetooth
├── K01cups-browsed -> ../init.d/cups-browsed
├── K01docker -> ../init.d/docker
├── K01irqbalance -> ../init.d/irqbalance
├── K01kerneloops -> ../init.d/kerneloops
├── K01lightdm -> ../init.d/lightdm
├── K01mysql -> ../init.d/mysql
├── K01saned -> ../init.d/saned
├── K01speech-dispatcher -> ../init.d/speech-dispatcher
├── K01thermald -> ../init.d/thermald
├── K01ubuntu-fan -> ../init.d/ubuntu-fan
├── K01ufw -> ../init.d/ufw
├── K01uuidd -> ../init.d/uuidd
├── K01vmware-tools-thinprint -> ../init.d/vmware-tools-thinprint
├── K01whoopsie -> ../init.d/whoopsie
├── K01xinetd -> ../init.d/xinetd
├── K02avahi-daemon -> ../init.d/avahi-daemon
├── K02cgroupfs-mount -> ../init.d/cgroupfs-mount
├── K02cups -> ../init.d/cups
├── K04rsyslog -> ../init.d/rsyslog
├── README
├── S01killprocs -> ../init.d/killprocs
└── S02single -> ../init.d/single


K로 시작하는 녀석들은 해당 서비스들을 종료하기 위한 스크립트로, 심볼릭 링크 원본의 스크립트를 stop인자와 함께 실행한다.
S로 시작하는 녀석들은 해당 서비스들을 구동하기 위한 스크립트로, 심볼릭 링크 원본의 스크립트를 start 인자와 함께 실행한다.

뒤에 있는 숫자는 순서를 맞추기 위함이다.


이런식으로 rc?.d 디렉토리들을 확인해보면, 런레벨 2~5와 S레벨의 경우 마지막에 /etc/init.d/rc.local 이라는 스크립트를 실행시킨다.

/etc/init.d/rc.local 스크립트를 살펴보면 내용은, /etc/rc.local 이라는 파일이 있을 경우 실행시킨다고 되어있다.


즉 런레벨 2~5, S의 경우 /etc/rc.local 이라는 스크립트를 부팅 과정 마지막에 실행시킨다는 것이다.


/etc/rc.local 스크립트 실행

Ubuntu16.04의 경우 런 레벨 2~5, S의 경우 /etc/rc.local를 최종적으로 실행시킨다. 해당 파일이 없을 경우 실행하지 않는다. 런레벨 0은 시스템 종료, 6는 재부팅이므로 관계 없고, 런레벨 1의 경우 시스템 복구 모두이기 때문에 복구를 위해서 해당 스크립트를 실행하지 않는것으로 보인다.



리눅스 부팅 스크립트 등록

리눅스 부팅 과정을 알아보면서 알 수 있듯이, 부팅때마다 실행되어야 할 스크립트는 /etc/rc.local에 입력하면 된다.


단, 주의할 사항은 PATH 같은 환경변수가 일반 쉘과 같은 환경으로 설정되지 않을수도 있기 때문에, 환경변수를 설정하고 명령어를 실행하거나, 절대경로로 실행하는 것을 추천한다.


또한 스크립트 실행 도중 에러가 발생했을 때, 표준 출력과 표준 에러를 직접 터미널로 확인하기 어려우므로 파일로 리디렉션(Redirection)하되, 표준 에러도 같이 리디렉션(Redirection)하도록 하는 것을 추천한다.


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

참조

https://www.thegeekstuff.com/2011/02/linux-boot-process/

http://kateee.tistory.com/51

http://nuitstory.tistory.com/500

https://wiki.debian.org/BootProcess

http://cherub.sungkyul.edu/~web/jinboard/files/63_boot.pdf

https://ko.wikipedia.org/wiki/%EC%8B%9C%EB%8F%99_%EC%9E%90%EC%B2%B4_%EC%8B%9C%ED%97%98

http://forensic-proof.com/archives/435

블로그에 수학 수식을 입력하는 방법은 다양합니다. 간단하게는 다른 수학 수식을 그려주는 곳에서 (e.g 한컴오피스) 수식을 그린 뒤, 해당 수식을 캡쳐해서 이미지 형태로 올릴 수도 있고, 아니면 직접 수식 모양대로 svg등으로 한땀 한땀 그릴 수도 있습니다. 아니면 흔히 다른 사람들이 많이 쓰는 라이브러리인 MathJax 등을 사용할 수도 있습니다. 저는 이번에 KaTeX라고 하는 라이브러리를 이용해서 블로그에 수식을 입력해보도록 하겠습니다.


https://khan.github.io/KaTeX/

KaTeX의 공식 홈페이지입니다. MathJax 보다 랜더링 속도가 빠르다는 것을 강점으로 홍보하고 있습니다.


참고로 LaTeX는 TeX라고 하는 조판 프로그램을 쉽게 사용하기 위해 만든 매크로입니다. LaTeX라는 것을 이용해서 특정한 의미를 갖는 메타캐릭터들과 텍스트들을 조합해서 PDF나 다른 문서들을 만들어낼 수 있습니다. 그 LaTeX에서 사용하는 매크로 중에서 수식을 그리는 매크로도 있는데, 이 KaTeX는 LaTeX의 이름을 바꾸어서 네이밍을 한 것 같습니다.



LaTeX는 자바스크립트 API를 지원하며, 다양한 방식으로 수식을 입력할 수 있는데, 여기서는 자바스크립트 API를 최대한 호출하지 않도록 간단하게 입력할 수 있는 Auto-Render Extension을 이용하겠습니다.


티스토리 관리자 페이지에서 '스킨 편집' - 'html 편집'을 누릅니다. 그리고 </head> 바로 윗 부분에 아래와 같이 코드 스니펫을 입력해줍니다.

아래 사진에는 Auto-Render Extension을 위한 값을 입력하지 않고 기본 katex라이브러리만 불러오는 방식으로 되어있지만, Auto-Render Exntension을 위해서는 아래 코드스니펫을 복사 밑 붙여넣기 해 줍니다.


CDN을 사용하지 않고, js파일과 css파일을 직접 본인의 서버에 올려서 사용하려고 한다면, prism.js 적용하는 것과 유사하게 파일업로드 후 상대경로를 지정해주면 됩니다.


 

	<!-- KaTex Start -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.9.0/katex.min.css" integrity="sha384-TEMocfGvRuD1rIAacqrknm5BQZ7W7uWitoih+jMNFXQIbNl16bO8OZmylH/Vi/Ei" crossorigin="anonymous">
<script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.9.0/katex.min.js" integrity="sha384-jmxIlussZWB7qCuB+PgKG1uLjjxbVVIayPJwi6cG6Zb4YKq0JIw+OMnkkEC7kYCq" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.9.0/contrib/auto-render.min.js" integrity="sha384-IiI65aU9ZYub2MY9zhtKd1H2ps7xxf+eb2YFG9lX6uRqpXCvBTOidPRCXCrQ++Uc" crossorigin="anonymous"></script>
<script>
	document.addEventListener("DOMContentLoaded", function() {
    renderMathInElement(document.body, {
			delimiters: [
				{left: "$$", right: "$$", display: true},
				{left: "//[", right: "//]", display: true},
				{left: "//(", right: "//)", display: false}
			]
		});
	});
</script>
	<!-- KaTex End -->


스니펫은 다음 링크에서도 확인할 수 있습니다.

https://github.com/Khan/KaTeX/blob/master/contrib/auto-render/README.md






그리고 테스트용 글을 한번 써 봅니다. 해당 API 문서를 참조해보면, 기본값으로 수식을 나타내는 구분자(delimiter)는 기본 설정 값으로 3개가 주어진다고 합니다.


$$ 수식 $$

\\[ 수식 \\]

\\( 수식 \\)


이러한 구분자의 값은 renderMathInElement 함수의 두번째 인자의 옵션에 설정하여 원하는 값으로 바꿀 수 있다고 합니다.

그리고 처음 첫번재 두번재 구분자는 display가 true값으로, 해당 구분자로 입력을 하면 해당 수식이 줄의 가운대 정렬이 되어서 displayMode로 크게 보여집니다. 하지만 마지막 구분자를 이용하면 displayMode가 false이므로 inline 모드로 입력이 되어 수식이 본문과 어우러지게 입력됩니다.


그리고 한글 자판을 사용하는 시스템에서 백슬래시 값을 입력하면 Won 기호로 인식되어서 두번째 세번째 구분자가 제대로 인식되지 않는 경우가 많습니다. 따라서 저 같은 경우에는 이 기본값의 구분자를 \ 대신 /으로 치환해서 사용합니다.


아래 그림은 $$ 구분자로 수식을 입력한 모습입니다.





원하는 수식으로 잘 랜더링 되었습니다.

$$A \equiv B(modC)$$



그리고 KaTeX에서 지원하는 구문들에 대한 레퍼런스 문서의 링크는 다음과 같습니다.

https://khan.github.io/KaTeX/function-support.html


KaTeX를 이용해서 구문을 작성할 시 참조하면 좋습니다.

컴퓨터를 사용함에 있어서 데이터 크기에 대한 단위들이 여러가지 있다. 그런 단위들에 대해 간략하게 알아보도록 한다.


- 비트(bit) 

https://en.wikipedia.org/wiki/Bit

비트는 Binary Digit의 약자이다. 직역하면 이진 숫자가 된다. 0아니면 1밖에 없으므로 이진(binary)가 맞으며, 숫자를 나타내는 것이 맞다. 이진법으로 나타낸 수의 한 자리에 차지하고 있는 숫자 하나를 의미한다고 봐도 의미가 맞다.


이 bit라는 용어는샤넌이라고 하는 사람이 1948년에 낸 논문에서 처음 사용했다고 한다. 저 샤넌이라고 하는 사람은 "정보공학의 아버지"라고 불린다고 한다. 수학자이면서, 전자전기공학자, 암호학자였고 bit라는 개념은 최초로 정보의 크기를 정의했다는 점에서 의미가 있다고 한다.

1946년에 애니악이 제작되었으므로, 컴퓨터 공학의 입장에서는 최초의 컴퓨터가 생긴지 얼마 안되었을 때 나타난 개념이다.


지금의 컴퓨터는 정보를 처리하는 수단으로서 주도적인 역할을 하고 있으니, 이때 정보의 크기를 규정할 수 있다는 것은 큰 의미가 있다고 볼 수 있다.


- 니블(nibble)

https://en.wikipedia.org/wiki/Nibble

니블은 4bit를 나타낸다. 하프 바이트(half-byte) 혹은 테트라드(tetrade)나 세미-옥텟(semi-octet), 쿼드비트(quadbit)나 쿼텟(quartet)이라고 불리기도 한다. 그리고 4비트는 10진수로 0부터 15까지의 수를 나타낼 수 있으므로 16진수(hexa-decimal)로 나타낸 수의 한 글자(digit)이라고 볼 수 있다. 따라서 hex-digit라고도 불린다. 하지만 요즘은 이러한 다양한 부르는 방법들을 잘 쓰지 않고, 궂이 언급한다면 hex code의 한 글자로서 간접적으로 불린다.

이러한 4비트에 따로 이름을 두어서 사용하는 이유는 10진수 한 자리 수(0~9)를 나타낼 수 있는 최소 정보단위가 4비트이기 때문이다.


- 바이트(byte)

https://en.wikipedia.org/wiki/Byte

원래의 의미는 글자 1글자를 나타내기 위한 용량을 뜻하게 되었는데, ASCII코드로 영어 대,소문자 및 일부 특수문자들을 다 표현할 수 있으므로, ASCII의 7bit에 패리티 비트 1bit를 붙여서 8bit로 영어 문자들을 다 표현할 수 있다. 이로써 1바이트가 8bit로 관례적으로 굳어지게 된다. 일반적으로 1바이트라고 하면 8비트를 뜻하게 된다.



2017년 12월 22일 기준, 마이크로소프트에서 제공하는 아래 링크에서 Windows 10 부팅 USB 제작 툴을 구할 수 있습니다. Windows 10의 부팅 USB와 해당 iso 파일은 무료로 배포되지만, 해당 운영체제에 사용되는 라이센스 키, 과거 CD로 설치하던 시절에는 CD-key라고 불리기도 했고, Product Key라고도 불리는 키는 돈을 주고 구매를 하거나 해야 합니다. 간혹 노트북을 구매 시, 윈도우 운영체제가 이미 설치되어 있는 경우, 노트북의 겉 면을 잘 찾아보면 윈도우 운영체제의 Product Key가 표시되어 있거나, 별도의 등록 절차를 통해서 키 인증을 받을 수 있는 경우가 있으므로 해당 사항은 좀더 찾아보시면 되겠습니다.


어쨋든 키를 가지고 있다고 가정하고 Windows 10 부팅 USB를 만들어 보도록 하겠습니다.


그리고 내용이 지워져도 상관없는 8GB 이상의 용량을 가진 USB 플래시 메모리도 필요합니다.



https://www.microsoft.com/ko-kr/software-download/windows10


위와 같은 웹 페이지가 나타나게 되는데, '지금 도구 다운로드' 버튼을 누르면 MediaCreationTool.exe라는 파일을 받을 수 있습니다. 해당 툴을 실행시켜보도록 하겠습니다.


당연 조건을 동의해주어야지 사용이 가능합니다. 동의를 누릅니다.

부팅 USB를 만드는 것이므로 두번째 라디오 박스를 선택합니다.

설정에 맞게 선택합니다. 에디션은 Windows 10만 가능하며, 아키텍쳐의 경우 CPU호환성을 확인해 보아야 하는데, 현재 대한민국 기준으로 64비트가 호환되지 않는 CPU는 거의 없으므로 저는 그대로 갑니다.

USB 플레시 메모리에 윈도우 부팅 이미지를 올릴 것이므로 첫번째 라디오 박스를 선택합니다.

지금 부착되어 있는 외장 스토리지에 맞게 선택합니다. 저 같은 경우에는 E드라이브에 외장 하드디스크가 있고, F드라이브에 USB 플래시 메모리가 있기에, F드라이브를 선택합니다.

시간이 다소 걸립니다. 침착하게 기다리도록 하겠습니다.

완료된 모습입니다.

안전하게 USB를 제거한 뒤 물리적으로 분리하도록 하겠습니다.


이제 이 USB를 이용하여 윈도우10을 원하는 기기에 설치하면 됩니다.

블로그에 소스코드를 넣어야 하는 경우가 있습니다. 이러할 경우 코드 하이라이터를 사용해주면 좋은데, 그 중에서도 꽤나 나이스한 디자인을 보여주는 prismjs를 티스토리 블로그에 적용해보도록 하겠습니다.


prismjs 홈페이지 주소입니다.

http://prismjs.com/index.html


공식 홈페이지에 가서 DOWNLOAD라는 버튼을 누릅니다.



다운로드 페이지로 가면, 필요한 구성요소를 직접 골라서 다운로드를 받을 수 있습니다. Compresion Level에는 개발버전과 Minified 버전이 있는데, 개발 버전은 prism.js의 소스코드를 변경해서 자신의 입맛대로 만들어 쓸 경우 필요한 버전입니다. 저희는 그냥 있는 버전을 사용하기만 할 것이므로 Minified version을 선택합니다.


테마의 경우 오른쪽에 있는 원들을 눌러서 하단에서 실제 적용된 테마의 모습을 확인할 수 있습니다. 저 같은 경우에는 Okaidia 테마가 마음에 드므로 해당 테마를 선택했습니다.

그 외에도 하이라이팅을 지원하는 언어들과, 다양한 플러그인들을 제공합니다. 저는 기본 제공하는 언어 외에 C++ 언어를 추가하였고, 플러그인은 줄 번호를 표시해주는 플러그인을 선택했습니다.




하단으로 내려가면 적용될 테마의 모습이 보입니다. 다운로드 JS와 다운로드 CSS를 한번씩 눌러서 prism.js와 prism.css 파일을 다운로드 받습니다.



그리고 티스토리 관리 페이지로 가서 꾸미기 탭의 HTML/CSS 편집으로 들어갑니다.


우측 상단에 보이는 파일 업로드를 누릅니다.


여기에 추가 버튼을 눌러서 prism.js 파일과 prism.css 파일을 업로드 해 줍니다.


파일들이 추가된 모습들이 보입니다. 이 파일들이 추가된 경로를 확인해놓습니다. 저의 경우에는 images/prism.js와 images/script.js 의 경로에 추가되었습니다.


그리고 다시 HTML을 눌러서 태그를 추가해야 합니다.

head 닫는 태그, 즉 </head> 바로 위에 위와 같이 추가해줍니다.

<script src="./images/prism.js"></script>
<link rel="stylesheet" href="./images/prism.css">


그리고 저장 버튼을 눌러서 적용해 주면 됩니다.


이후 코드 하이라이팅이 필요한 경우 에디터에서 HTML 모드를 활성화 한 뒤 다음 태그를 입력해주면 됩니다.

<pre class="line-numbers language-cpp"> 
<code class="language-cpp">
//여기에 소스코드를 작성하시면 됩니다.
</code>
</pre>


HTML 모드에서 코드를 작성하려고 하면 <나 >와 같은 문자들을 또 수동으로 &gt; &lt; 등으로 이스케이프 처리해주어야 합니다. 따라서 추천하는 방법은 HTML모드에서 pre와 code 태그만 작성한 뒤, 위지윅 모드에서 소스코드를 붙여넣기하는 방법입니다.


컴퓨터를 오래 사용하다가 보면, 컴퓨터가 많이 느려진다던지, 바이러스에 걸린다던지, 설정이 잘못되었다던지 등의 이유로 컴퓨터의 초기화가 필요할만한 상황이 있습니다. 이럴때 보통 사람들은 컴퓨터를 '포맷' 한다고 들 많이 표현을 합니다.


하지만 보통 이럴 때 사용하는 방법은 '포맷'이 아니라 '윈도우 재설치'라는 용어가 맞습니다. 간단하게 설명해서 '포맷'은 저장장치의 내용을 다 지워버리고, 새로 파일시스템을 구축하는 것이라고 보면 되고, '윈도우 재설치'는 컴퓨터의 시스템 관리 소프트웨어, 즉 운영체재를 지우고 새로 설치하는 것이라고 볼 수 있습니다.


그래서 단순히 컴퓨터가 이상해졌다고 하드디스크(혹은 SSD)를 '포맷'만 한다면 부팅이 되지 않는 그냥 고철덩어리 컴퓨터 하드웨어만 남게 되는 것이지요. 


어쨋든 용어는 바로 잡았으니, '포맷', 아니, '윈도우 재설치'를 하는 개괄적인 과정에 대해서 설명해 보도록 하겠습니다. 보통 주변의 컴퓨터를 잘 아는 사람에게 부탁하는 것이 일반적이기도 한데요, 전체적인 개념을 알고 인터넷을 조금 찾아보면 누구나 할 수 있는 과정이기도 합니다. 일단 필요한 것들은 다음과 같습니다.


1. 윈도우 라이센스 키

2. 윈도우 재설치를 할 노트북 혹은 데스크탑 컴퓨터

3. 내용이 다 지워져도 되는 8GB이상의 용량을 가진 USB 메모리 (혹은 윈도우 설치용 CD)

4. 그리고 부팅 USB를 만들때 쓸 컴퓨터


윈도우 버전에 따라서 용량이 다르기 때문에 USB 메모리가 꼭 8GB이상의 용량을 가질 필요는 없지만 안정적으로 하기 위해서는 8GB이상의 용량을 확보하는 것이 좋습니다.


컴퓨터에 관심이 크게 없으신 분들은 윈도우 라이센스에 대한 개념이 없으신 분도 있는데, 윈도우 운영체제는 10만원대 정도의 가격을 가진 '상용 제품'입니다. 즉, 돈을 받고 판매를 하는 하나의 상품이며, 정당한 대가를 지급하고 사용하는 것이 맞습니다. 그런데 보통 삼성, LG와 같은 곳에서 노트북을 사게 되면 윈도우가 기본적으로 설치되어 있는 경우가 많은데, 그런 경우는 노트북 가격에 윈도우 운영체제 가격이 포함되어 있는 것입니다. 그러한 노트북은 노트북에 붙어있는 스티커를 잘 찾아보면 윈도우 라이센스 키(시리얼 키)가 있을 것입니다. 이 키를 활용해서 윈도우 재설치를 할 수 있습니다. 혹은 이미 윈도우 운영체제를 사용하다가, Microsoft 계정으로 로그인 뒤 해당 윈도우즈 운영체제의 라이센스를 계정에다가 귀속시킨 경우, 해당 계정을 통하여 다시 라이센스를 복구할 수도 있는 것으로 알고 있습니다. 이에 대한 자세한 과정과 내용은, 다른 블로그나 Microsoft 공식 사이트, 도움말 등을 참고해 주시면 되겠습니다.


그러면 윈도우 재설치의 개괄적인 전체 흐름을 나열해보도록 하겠습니다.


1. 윈도우 라이센스 키 확보 (버전, 에디션 확인 필수!)

2. 해당 윈도우 버전에 맞는 ISO 파일 확보

3. ISO 파일을 이용하여 USB 메모리를 윈도우즈 부팅 USB로 제작

//혹은 2-3번 과정을 동시에 진행을 할, MediaCreationTool.exe를 이용하여 윈도우즈 부트 USB를 만들기

4. USB를 꽂은 상태에서 재설치 할 컴퓨터를 재부팅

5. 해당 컴퓨터의 BIOS 모드로 진입(혹은 UEFI 모드)후, 부팅 우선 순위(Boot Priority)를 변경하여 'USB 메모리'의 우선순위를 하드디스크나 SSD보다 높게 설정

6. USB로 부팅 시 윈도우 재설치 메뉴가 활성화됨. 절차에 따라서 재설치

7. 윈도우 재설치 이후 해당 하드웨어에 맞는 드라이버 파일 설치

8. 기타 필요한 한컴오피스나, MS 오피스 파일 등을 설치


전체적인 흐름은 다음과 같습니다. 2~3번 과정은 한번에 해결해주는 프로그램을 마이크로소프트에서 지원한다고 들은바가 있는 것도 같습니다. 각각의 과정에 대하여 상세하게 설명하면 하나하나 더 상세히 설명을 할 수 있지만, 그렇게 하게 되면 '간단 설명'이라는 이 포스팅의 성격과 달라지므로 이 포스팅은 여기서 끝마치겠습니다.

+ Recent posts