2017년 11월 23일 목요일

python에서 Linux shell command 사용하기





파이썬에서 Linux의 shell command를 사용하는 방법이다.
이를 위해서는 파이썬의 os모듈과 sys모듈을 import해야 한다.
다음은 코드 조각이다.

import os
import sys

os.system('cat qqq.txt > /dev/ttyPS0')

위의 소스코드는 현재 디렉토리에 있는 qqq.txt라는 파일의 내용을 ttyPS0라는 장치(리눅스에서는 장치도 file로 취급)로 전송하는 기능을 수행한다.
여기서 ttyPS0는 현재 디바이스가 가지고 있는 Serial port이다. 만일 현재 디바이스가 임베디드 장비이고 이 장비의 USB UART에 USB 케이블로 PC와 연결되어 있다면 위의 코드를 실행하고 PC쪽에서 Serial 포트의 데이터를 읽는 프로그램을 만들면 임베디드 장비의 qqq.txt의 내용을 PC에서 수신할수 있게 될것이다.

혹은 반대로 하면

os.system('cat /dev/ttyPS0')

이상과 같이 하면 현재의 장비의 Serial port로 들어오는 데이터를 터미널 창에 표시해주는 리눅스의 shell command를 python에서 사용하는 방법이었다. 이 경우는 PC에서 Serial port로 전송하는 데이터를 임베디드 장비에서 수신할수 있는 쉘 명령어를 python에서 사용한 방식이 되겠다.

만일 shell command의 내용을 변수에 저장하고자 한다면 subprocess라는 것을 import해 주어야 한다.

import subprocess

aaa = subprocess.check_output(['cat', 'kkk.txt'])
print aaa

와 같이 하면 kkk.txt의 내용을 변수 aaa에 저장했다가 이것을 출력하는 코드가 되겠다.

혹은 

mylist = subprocess.check_output(['ls', '-l'])
print mylist

이렇게하면 현재 디렉토리에 있는 파일 목록을 변수 mylist에 담고 그것을 출력하는 기능을 수행하는 코드이다.

혹은 보다 간단한 방법은 shell 옵션을 True로 하면 터미널 창에서 입력하는 형태 그대로의 command를 사용할수 있다.

pid = subprocess.check_output('ps -elf | grep CRSViewer.py', shell=True)


이렇게 하면 CRSViewer.py의 실행 process id를 나타내 준다.


2017년 11월 22일 수요일

C# 초 간단 쓰레드(Thread) 예제





"Start Thread" 버튼 클릭시 0.5초 간격으로 1부터 순차적으로 숫자를 출력하고 "Stop Thread" 버튼 클릭시 쓰레드를 종료하는 초 간단 C#용 Thread 예제 코드이다.
화면 구성은 다음과 같다.


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ExSerialRead
{
    public partial class Form1 : Form
    {
        private int cnt = 0;
        private Thread rTh;

        public Form1()
        {
            InitializeComponent();
        }

        private void btnStartThread_Click(object sender, EventArgs e)
        {
            //Thread 객체 생성. 생성시 이 Thread가 실행할 메소드를 지정해 준다. 
            //여기서는 Count라는 메소드를 rTh라는 쓰레드가 실행하게 될 것이다.
            rTh = new Thread(Count);
            rTh.Start();
        }

        // Thread로 수행할 작업
        private void Count()
        {
            while(true)
            {
                ++cnt;
                Thread.Sleep(500);
                //Console.WriteLine("crr cnt : " + cnt); 
                Console.WriteLine("crr cnt is {0} ", cnt); 

                if (cnt > 200)
                {
                    rTh.Abort(); //쓰레드 강제 종료

                    Console.WriteLine("Thread 종료. cnt : " + cnt);
                    break;
                }
            }
        }

        private void btnStopThread_Click(object sender, EventArgs e)
        {
            rTh.Abort(); //쓰레드 강제 종료
            Console.WriteLine("Thread 종료~");
        }
    }
}



2017년 11월 13일 월요일

dd command를 이용한 리눅스 시스템 전체를(디스크 전체 혹은 파티션 전체를) 부팅 가능 USB로 복사하기





dd command를 이용한 리눅스 시스템 전체를(디스크 전체 혹은 파티션 전체를) 부팅 가능 USB로 복사하기
(Ubuntu를 중심으로)

리눅스를 사용하다보면 현재의 시스템 설정상태, 현재 설치되어있는 각종 패키지들의 그 상태 그대로 시스템 전체를 백업 받을 일이 종종 발생한다.

시스템 해킹에 대한 복구 차원에서도 현재의 시스템 그대로를 복제해 두는 일은 필요하다.
또한 리눅스를 탑재한 임베디드 시스템의 경우 해당 시스템이 가동되는데 필요한 패키지들이 다 설치된 상태 그대로 제품 양산시 SD card에 그대로 시스템을 복제해야 할 경우등에도 꼭 필요한 작업이 디스크 전체(현재의 리눅스 시스템 전체)를 복제하는 일이다.

특별히 임베비디 장비의 경우 리눅스가 최신 버전이 설치되기 보다는 옛날 버전을 설치하는 경우가 흔한데 이렇게 구 버전의 리눅스 시스템의 경우 필요한 패키지들을 설치하는 작업이 여간 번거러운 작업이 아니다.
게다가 시스템 architecture가 흔히 쓰는 경우가 아닐경우는 정람 패키지 설치 작업이 난감한 경우들이 있다.
이럴 경우 설치 패키지들을 다운 받아서 off-line 상태에서 dpkg를 이용해 설치하는 궁여지책을 쓰는 경우도 있지만 그러나 이것도 제품 양산을 염두에 둔다면 그렇게 쓸모가 좋은 모양새는 아니다.
그래서 현재의 리눅스 시스템 전체(디스크 전체)를 복제하는 것이 매유 요긴해 진다.
그런데 이런 기능을 제공해주는 툴들이 리눅스는 매우 다양하다.
remastersys, genisoimage, partimage, gnome-disks, clonezilla... 
그런데 이런 툴들도 구버전 리눅스 시스템에서는 아예 설치가 안되는 경우도 있고 어떤 건 구버전에서만 기능이 동작하는 경우도 있는 등 쉽지 않는 작업이다.
리눅스 자체가 한 회사에서 만든 Windows와 달리 수 많은 사람들에 의해서 만들어지다 보니 그럴수 밖에 없다.

아무튼 구버전, 신버전 등 가리지 않고 위의 목적을 달성할수 있는 아주 좋은 command가 다름아닌 dd이다.
명령어 같지 않게 생긴 강력한 명령어가 dd이다.
dd는 원래는 Data Duplicator를 뜻하는 명령어인데 이걸 잘못 사용하면 디스크 자체를 통체로 날려먹는 경우들이 있어 Disk Destroyer라는 별명이 붙을 있을 정도이다.

dd command는 리눅스 시스템 차원에서의 command이기 때문에 별도의 패키지를 설치할 필요가 없다.
dd가 할수 있는 기능은 다양하다. 그러나 본 포스트에서는 아래의 미션을 위한 것으로 한정하고자 한다.

-. 임베디드 시스템의 현재의 설치된 패키지, 현재의 설정된 시스템 상태 그대로를 USB 메모리에 복제를 한다.

-. 복제된 USB 메모리는 부팅이 가능해야 한다.

-. 복제된 USB 메모리를 동일한 임베디드 보드에 꽂으면 해당 임베디드 보드도 부팅시 현재의 리눅스 시스템과 모든 조건이 동일한 시스템으로 동작이 되어야 한다.

작업을 위해 필요한 조건 혹은 필요한 상태

-. 임베디드 시스템에 USB 외부 메모리가 mount되어 있다. 이곳에 시스템 복제본이 저장될 공간이다.
   (외부 USB 메모리 마운트는 Disk Utility라는 기본 설치된 프로그램을 실행해서 해도 된다. 혹은 터미널 창에서 마운트를 해도 된다)

dd command 기본 사용법

# dd if=복제할_대상이_되는_디스크_장치_이름 of=복제본을_저장할_마운트된_USB_장치의_이름 bs=복사속도

위의 옵션들에 들어갈 정보는 fdisk -l 명령어를 통해서 확인할수 있다. 이 명령어의 결과는 다음과 같은 정보들이 표시된다.

root@joe-VirtualBox:/home/joe/다운로드# fdisk -l
Disk /dev/sda: 30.2 GiB, 32377438208 bytes, 63237184 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xe46ece9d

Device     Boot    Start      End  Sectors  Size Id Type
/dev/sda1  *        2048 54849535 54847488 26.2G 83 Linux
/dev/sda2       54851582 63236095  8384514    4G  5 Extended
/dev/sda5       54851584 63236095  8384512    4G 82 Linux swap / Solaris


Disk /dev/sdb: 3.8 GiB, 4009754624 bytes, 7831552 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x04831162

Device     Boot  Start     End Sectors  Size Id Type
/dev/sdb1  *        63  262207  262145  128M  c W95 FAT32 (LBA)
/dev/sdb2       262208 6291455 6029248  2.9G 83 Linux

위 정보를 보면 2개의 디스크가 현재 리눅스 시스템에 마운트 되어 있음을 알수 있다.
여기서 주목해야할 정보는 
첫 번째 디스크의 장치명과 용량은 
Disk /dev/sda: 30.2 GiB ...
-. 장치명 : /dev/sda
-. 용량 : 30.2 Gb
-. partition 정보 : sda1, sda2, sda5

두 번째 디스크의 장치명과 용량은 
Disk /dev/sdb: 3.8 GiB
-. 장치명 : /dev/sdb
-. 용량 : 3.8 Gb
-. partition 정보 : sdb1, sdb2

아무튼 위의 정보들로부터 dd에서 사용하게 될 정보들이 다 나와있다.
dd의 if는 Input File의 약자이고 of는 Output File의 약자이다.
우리는 현재의 리눅스 시스템이 설치되어 있는 디스크인 /dev/sda에 있는 모든 것들을(부팅 영역까지) /dev/sdb에 복제를 하고자 한다.

# dd if=/dev/sda of=/dev/sdb bs=64K

이렇게 하면 USB 메모리에 완전한 형태로의 시스템이 그대로 복제되었다.