파일시스템 사용량 추이를 http 전송으로 DB에 누적하기
2022.08.29 10:58
원문 : http://www.ischo.net -- 조인상 // 시스템 엔지니어
Writer : http://www.ischo.net -- ischo // System Engineer in Replubic Of Korea
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
파일시스템 사용량 추이를 http 전송으로 DB에 누적하기
시스템 관리를 하다보면 각 서버들의 파일시스템 추이를 관리해야 할 필요가 있다.
파일시스템은 갈수록 크기가 커지며, 하루에 얼마나 쌓이는지 알아야지 향후 저장공간을 증설할때 얼마만큼의
저장공간을 마련해야 할지 예측할 수 있기 때문이다.
또는 정기적인 에방점검을 할때 보고서를 작성하는 경우에도 파일시스템 용량 체크는 상당한 노력이 든다.
수십대가 넘는 시스템들의 파일시스템 추이를 매달 기록해서 제출해야 할 때 매우 번거롭다.
단순, 반복작업만큼 자동화에 걸맞는 대상도 없다.
이 문서에서는 각 Windows, Linux 시스템에서 쉘스크립트를 통해서 매일 파일시스템 용량을 각 호스트에 저장하면서
동시에 httpd 웹서버로 전송하여 향후에 추이도 계산할 수 있는 프로그래밍에 대해서 다룬다.
차례
1. php 웹서버 구성
2. 데이터베이스 구성
3. Linux 서버 쉘스크립팅
4. Windows 서버 쉘스크립팅
5. 데이터 수집 처리 및 조회
1. php 웹서버 구성
먼저 php 웹서버를 구성한다.
apache, php, mysql 이 일반적이지만, 다른 구성이라도 문제없다.
HTTP GET 방식으로 들어온 데이터를 DB에 처리할 예정이다.
예제에서는 <Document Root> 디렉토리 안에 fsmonitor 라는 디렉토리를 만들어서 수행하였다.
2. 데이터베이스 구성
- 데이터베이스 만들기 :
: fsmonitor 라는 데이터베이스를 만든다.
mysql> create database fsmonitor;
mysql> CREATE DATABASE fsmonitor CHARACTER SET utf8 COLLATE utf8_bin;
mysql> CREATE USER 'fsmonitor'@'localhost' IDENTIFIED BY 'password' PASSWORD EXPIRE NEVER;
mysql> GRANT ALL PRIVILEGES ON fsmonitor.* TO 'fsmonitor'@'localhost';mysql> flush privileges;
- 테이블 생성
mysql> CREATE TABLE fsmonitor_tb (
sno int(11) NOT NULL auto_increment PRIMARY KEY,
date char(8) DEFAULT NULL,
servername varchar(80) DEFAULT NULL,
hostname varchar(80) DEFAULT NULL,
ipaddress char(20) DEFAULT NULL,
mount varchar(80) DEFAULT NULL,
size varchar(80) DEFAULT NULL,
used varchar(80) DEFAULT NULL,
free varchar(80) DEFAULT NULL,
perc varchar(80) DEFAULT NULL,
etc varchar(100) DEFAULT NULL
) DEFAULT CHARSET=utf8;
- 테이블 명세
sno int(11) : 순번
date char(8) : 날짜 YYYYMMDD 형식
servername varchar(80) : 서버이름
hostname varchar(80) : hostname
ipaddress char(20) : IP주소
mount varchar(80) : 마운트명 ( / 또는 C드라이브)
size varchar(80) : 전체 용량
used varchar(80) : 사용량
free varchar(80) : 남은용량
perc varchar(80) : 사용율
etc varchar(100) : 기타
3. Linux 서버 쉘스크립팅
- 다음 df.sh 쉘스크립트 파일을 작성한다.
스크립트는 현재 사용량을 로컬 df_연도.txt 파일에 증분하여 기록한 후 해당 웹서버의 DB에 기록한다.
- Linux서버에 curl 이 설치되어 있어야 한다.
# yum install curl
- 쉡스크립트 : df.sh
#!/bin/bash
################################################
# Program : Logging filesystem utilization #
# Daeshin Networks #
################################################
## SET ENVIRONMENT #############################
DATE=`date +%Y%m%d`
YEAR=`date +%Y`
SH_HOME=/home/dsnw
LOGFILE=${SH_HOME}/df_${YEAR}.log
TMPFILE=${SH_HOME}/df_temp.log
HOSTNAME=`hostname`
GW_NIC=`netstat -nr | grep UG | awk {'print $8'}`
IP=`ip add | grep inet | grep ${GW_NIC} | awk {'print $2'} | cut -d "/" -f 1`
################################################## MAIN ########################################
export LANG=C
date >> ${LOGFILE}
df -h >> ${LOGFILE}
echo >> ${LOGFILE}df -h | grep -v "Filesystem" | grep -v "Use%" | grep -v /run | grep -v /sys | grep -v tmpfs | grep -v /boot > ${TMPFILE}
while read LIST
do
SIZE=`echo ${LIST} | awk {'print $2'}`
USED=`echo ${LIST} | awk {'print $3'}`
FREE=`echo ${LIST} | awk {'print $4'}`
PERC=`echo ${LIST} | awk {'print $5'}`
MOUNT=`echo ${LIST} | awk {'print $6'}`
curl "http://<SERVER_IPADDRESS>/fsmonitor/insert.php?date=${DATE}&host=${HOSTNAME}&ip=${IP}&size=${SIZE}&used=${USED}&free=${FREE}&perc=${PERC}&mount=${MOUNT}"sleep 1
done < ${TMPFILE}
- 해당 쉘스크립트에 실행권한을 주고 테스트 한다.
# chmod 700 df.sh
# ./df.sh
: 결과로 df_2022.log 파일이 생성되고, 데이터베이스에 파일시스템 추이가 기록된다.
4. Windows 서버 쉘스크립팅
- Windows 에서도 curl 을 설치해야 한다. 첨부의 curl.exe 다운로드.
- 시스템에서 파워쉘 실행권한을 주기 위해서 다음 명령어를 실행한다.
PS> Set-ExecutionPolicy RemoteSigned
- 파워쉘스크립트 : df.ps1
Function Get-DiskFreeSpace
{
Get-WmiObject Win32_LogicalDisk -Filter "DriveType=3" | Format-Table -AutoSize `
@{Label="DiskDrive";Expression={$_.DeviceID + ","}},`
@{Label="Size";Expression={($_.Size/1gb) -as [int]};FormatString="{0:N1}G,"},`
@{Label="Used";Expression={($_.Size/1gb)-($_.FreeSpace/1gb) -as [int]};FormatString="{0:N1}G,"},`
@{Label="Avail";Expression={($_.FreeSpace/1gb) -as [int]};FormatString="{0:N1}G,"},`
@{Label="Use%";Expression={(($_.Size/1gb)-($_.FreeSpace/1gb))/($_.Size/1gb) * 100 -as [int]};FormatString="{0:N1}%"}
}$HOSTNAME = $env:computername;
$IPADDRESS = (get-netadapter | get-netipaddress | ? addressfamily -eq 'IPv4').ipaddress|?{$_ -notmatch '169.254.'}|?{$_ -notmatch '10.0.'}|?{$_ -notmatch '10.100.'}|Select-Object -First 1;
$DATE = date;
$DATE = $DATE.ToString("yyyyMMdd");if(![System.IO.Directory]::Exists("C:\dsnw\")){
New-Item -ItemType Directory -Path "C:\dsnw\";
}if(![System.IO.File]::Exists("C:\dsnw\df.log")){
New-Item -ItemType File -Path "C:\dsnw\df.log";
}if(![System.IO.File]::Exists("C:\dsnw\df.tmp")){
New-Item -ItemType File -Path "C:\dsnw\df.tmp";
}if([System.IO.File]::Exists("C:\dsnw\df.log")){
Get-DiskFreeSpace >> "C:\dsnw\df.log"
Get-DiskFreeSpace > "C:\dsnw\df.tmp"
}$FILE = Get-Content "C:\dsnw\df.tmp"
$result=@()foreach ($LINE in $FILE)
{foreach ($COL in $LINE)
{
$result=$LINE -split ","
$MOUNT=$result[0]
$SIZE=$result[1]
$USED=$result[2]
$FREE=$result[3]
$PERC=$result[4]
}if($MOUNT -match "DiskDrive*" -or $MOUNT -match "---------*" -or $MOUNT -eq ""){
continue;
} else {
$MOUNT=$MOUNT.Trim();
$SIZE=$SIZE.Trim();
$USED=$USED.Trim();
$FREE=$FREE.Trim();
$PERC=$SIZE.Trim();
"curl http://pcs.kipf.re.kr/fsmonitor/insert.php?date=${DATE}&host=${HOSTNAME}&ip=${IPADDRESS}&size=${SIZE}&used=${USED}&free=${FREE}&perc=${PERC}&mount=${MOUNT}"
}
}
5. 데이터 수집 처리 및 조회
- 데이터베이스 연결 : db_connect.php
<?php
$servername="localhost";
$user="fsmonitor";
$password="password";
$db="fsmonitor";$connect=mysqli_connect($servername,$user,$password,$db);
if (!$connect) {die ("Failed to connect! : ".mysqli_connect_error());
}
?>
- 데이터 수집 처리 : insert.php
<?php
include "./db_connect.php";
$DATA_DATE = $_GET['date'];
$DATA_HOST = $_GET['host'];
$DATA_IP = $_GET['ip'];
$DATA_SIZE = $_GET['size'];
$DATA_USED = $_GET['used'];
$DATA_FREE = $_GET['free'];
$DATA_PERC = $_GET['perc'];
$DATA_MOUNT = $_GET['mount'];
$query = "insert into fsmonitor_tb(date,hostname,ipaddress,mount,size,used,free,perc) values('$DATA_DATE','$DATA_HOST','$DATA_IP','$DATA_MOUNT','$DATA_SIZE','$DATA_USED','$DATA_FREE','$DATA_PERC');";$result = mysqli_query($connect,$query) or die("database query error");
mysqli_close($connect);?>
- 데이터 조회 : list.php (첨부 list.zip 압축해제)
<?php
include "./db_connect.php";echo "
<head>
<style>
.bordernone{
border-collapse : collapse;
border : 0px solid;
margin-left : auto;
margin-right : auto;
}
#borderset{
border-collapse : collapse;
border : 1px solid;
margin-left : auto;
margin-right : auto;
}
#borderset td{
padding : 4px;
border : 1px solid;
text-align : center;
}
</style>
</head><body>
<form method='get'>
<table style='margin-left : auto; margin-right : auto; class='bordernone'>
<tr>
<td>From date <input type='text' name='input_from_date' /></td>
<td> To date <input type='text' name='input_to_date' /></td>
<td>IPaddress <input type='text' name='input_ip' /></td>
<td>Mount Point <input type='text' name='input_mount' /></td>
</tr>
</table>
<br>
<center><input type='hidden' name='sc' value='ok' /><table style='margin-left : auto; margin-right : auto;' class='bordernone'>
<tr>
<td><center><button type='button'><a href='http://<SERVER_IPADDRESS>/fsmonitor/list.php'>Refresh</a></button></center></td>
<td><center><input type='submit' /></center></td>
</tr>
</table>
<br>
<br>
</form>";
$query1 = "select * from fsmonitor_tb";
$query2 = "";if($_GET['input_from_date'] != NULL || $_GET['input_to_date'] != NULL || $_GET['input_ip'] != NULL || $_GET['input_mount'] != NULL)
{
$query2 = " where ";
}if($_GET['input_from_date'] != NULL){
$query2 .= "date between '".$_GET['input_from_date']. "' and '".$_GET['input_to_date']."'";
}if($_GET['input_ip'] != NULL){
if($_GET['input_from_date'] != NULL && $_GET['input_to_date'] != NULL) {
$query2 .= " and ";
}
$query2 .= "ipaddress='".$_GET['input_ip']."'";
}if($_GET['input_mount'] != NULL){
if(($_GET['input_from_date'] != NULL && $_GET['input_to_date'] != NULL) || $_GET['input_ip'] != NULL) {
$query2 .= " and ";
}
$query2 .= "mount='".$_GET['input_mount']."'";
}$query3 = " order by date,ipaddress,mount";
$query = $query1.$query2.$query3.";";
$result = mysqli_query($connect,$query) or die("db die");
if($_GET['sc'] == 'ok' ){
echo "
<div style='text-align:center'>
<table id='borderset' border='1' style='margin-left : auto; margin-right : auto;' >
<tr>
<td>NO</td>
<td>DATE</td>
<td>HOSTNAME</td>
<td>IP</td>
<td>MOUNT POINT</td>
<td>SIZE</td>
<td>USED</td>
<td>FREE</td>
<td>PERCENT</td>
</tr>
";while ($row = mysqli_fetch_array($result)) {
echo "<tr>
<td>".$row['sno']."</td>
<td>".$row['date']."</td>
<td>".$row['hostname']."</td>
<td>".$row['ipaddress']."</td>
<td>".$row['mount']."</td>
<td>".$row['size']."</td>
<td>".$row['used']."</td>
<td>".$row['free']."</td>
<td>".$row['perc']."</td>
</tr>";}
echo "
</table>
</div>
";# end of if
}echo "
</body>
";
mysqli_close($connect);?>
- 데이터 조회
웹브라우저에서 http://<SERVER_IPADDRESS>/fsmonitor/list.php 로 검색.