[Scripts] tìm và khoá user không hoạt động trong vòng 90 ngày trên active directiory

Script tìm và disable các account không đăng nhập trong vòng 90 ngày trên AD

# disableUsers.ps1  
# Set msDS-LogonTimeSyncInterval (days) to a sane number.  By
# default lastLogonDate only replicates between DCs every 9-14 
# days unless this attribute is set to a shorter interval.
 
# Also, make sure to create the EventLog source before running, or
# comment out the Write-EventLog lines if no event logging is
# needed.  Only needed once on each machine running this script.
# New-EventLog -LogName Application -Source "DisableUsers.ps1"
 
# Remove "-WhatIf"s before putting into production.
 
Import-Module ActiveDirectory
 
$inactiveDays = 90
$neverLoggedInDays = 90
$disableDaysInactive=(Get-Date).AddDays(-($inactiveDays))
$disableDaysNeverLoggedIn=(Get-Date).AddDays(-($neverLoggedInDays))
 
# Identify and disable users who have not logged in in x days
 
$disableUsers1 = Get-ADUser -Filter {Enabled -eq $TRUE} -Properties lastLogonDate, whenCreated, distinguishedName | Where-Object {($_.lastLogonDate -lt $disableDaysInactive) -and ($_.lastLogonDate -ne $NULL)}
 
 $disableUsers1 | ForEach-Object {
   Disable-ADAccount $_
   #Write-EventLog -Source "DisableUsers.ps1" -EventId 9090 -LogName Application -Message "Attempted to disable user $_ because the last login was more than $inactiveDays ago."
   }
 
# Identify and disable users who were created x days ago and never logged in.
 
$disableUsers2 = Get-ADUser -Filter {Enabled -eq $TRUE} -Properties lastLogonDate, whenCreated, distinguishedName | Where-Object {($_.whenCreated -lt $disableDaysNeverLoggedIn) -and (-not ($_.lastLogonDate -ne $NULL))}
 
$disableUsers2 | ForEach-Object {
   Disable-ADAccount $_
   #Write-EventLog -Source "DisableUsers.ps1" -EventId 9091 -LogName Application -Message "Attempted to disable user $_ because user has never logged in and $neverLoggedInDays days have passed."
   }

 

Xử lý lỗi crontab truncate command

Case: Nhét 1 đoạn mysqldump vào crontab để backup db hàng đêm. Sáng hôm sau kiểm tra ko thấy file dump đâu.
đoạn command khai báo crontab

0 0 * * * /usr/bin/mysqldump -uzabbixuser -pMikita zabbixdb > /opt/backup/zabbixdb-`date +%F`.sql

Giải quyết ra sao?
chạy bằng crontab nên output lúc chạy sẽ được ném vào /var/mail/<user>
Ở đây chúng ta chạy cron trên user root, check file /var/mail/root

From root@devopsvn.xyz.localdomain  Tue Mar 31 00:00:01 2020
Return-Path: <root@devopsvn.xyz.localdomain>
X-Original-To: root
Delivered-To: root@devopsvn.xyz.localdomain
Received: by devopsvn.xyz.localdomain (Postfix, from userid 0)
        id 1FCA36000345; Tue, 31 Mar 2020 00:00:01 +0700 (+07)
From: root@devopsvn.xyz.localdomain (Cron Daemon)
To: root@devopsvn.xyz.localdomain
Subject: Cron <root@devopsvn.xyz> /usr/bin/mysqldump -uzabbixuser -pMikita zabbixdb > /opt/backup/zabbixdb-`date +
Content-Type: text/plain; charset=UTF-8
Auto-Submitted: auto-generated
X-Cron-Env: <LANG=en_US.UTF-8>
X-Cron-Env: <SHELL=/bin/sh>
X-Cron-Env: <HOME=/root>
X-Cron-Env: <PATH=/usr/bin:/bin>
X-Cron-Env: <LOGNAME=root>
X-Cron-Env: <USER=root>
Message-Id: <20200330170001.1FCA36000345@devopsvn.xyz.localdomain>
Date: Tue, 31 Mar 2020 00:00:01 +0700 (+07)

/bin/sh: -c: line 0: unexpected EOF while looking for matching ``'
/bin/sh: -c: line 1: syntax error: unexpected end of file

Để ý dòng subject, thấy command của chúng ta bị cắt mất còn 1 đoạn ngắn xíu, nguyên nhân do ký tự %

Percent-signs (%) in the command, unless escaped with backslash (\), 
will be changed into newline characters, and all data after the 
first % will be sent to the command as standard input.

tiến hành escape ký tự %, cron thay đổi thành

0 0 * * * /usr/bin/mysqldump -uzabbixuser -pMikita zabbixdb > /opt/backup/zabbixdb-`date +\%F`.sql

lưu lại crontab.

Script nén log file, sau đó move sang thư mục backup

Gồm 2 script, cơ chế:
– Dọn nén các file .log trong folder chứa log, ở đây là /opt/batch/<tên batch>/log (Điều chỉnh tron file chạy chính)
– Sau khi nén xong thì đưa lên file server để chứa: ở đây đã mount file server vào /net/filesv (cấu hình điều chỉnh trong file thứ cấp)
– Các file log được dọn là các file log có từ tháng trước, và hiện tại không có tiến trình nào đang đọc ghi: ví dụ: hnay là tháng 8 thì sẽ dọn các file có timestamp là tháng 7

File chạy chính, clean_all_log.sh

#!/bin/bash

## find all directory named log or logs and call clean_log_batch.sh script 


START=$(date +%s)

function timecal {
        END=$(date +%s)
        TOTAL=$(expr $END - $START)
        HOURS=$(expr $TOTAL / 3600)
        MINUTES=$(expr $TOTAL % 3600 / 60)
        RUNNING_TIME="$MINUTES minute(s)"
        [[ $HOURS -gt 0 ]]&&{ RUNNING_TIME="$HOURS hour(s), $RUNNING_TIME"; }
        echo "[INFO] Total time: $RUNNING_TIME"
}

trap "timecal" EXIT

BASEDIR=$(dirname $0)
## batch dir, value must be absolute path
BATCH_DIR=/opt/batch
[ ! -d $BATCH_DIR ]&&{ echo $BATCH_DIR not found; exit 1; }
LOG_DIRS=$(find $BATCH_DIR -type d -name 'log' -or -name 'logs')
for LOG_DIR in $LOG_DIRS
do
	echo "[INFO] Clean log path $LOG_DIR"
	./clean_log_batch.sh $LOG_DIR	
done

File thứ cấp: clean_log_batch.sh

#!/bin/bash

## This script requires autofs installed on the running machine
## and read/write on REMOTE_HOST via nfs share
## LOG_DIR must be absolute path

## Log file must have timestamp in its name with format YYYY[.-_]mm[/-_]dd
## Log file must have .log in its name
## Log file must have its name pattern placed before timestamp
## Even so, cover all the log pattern generated by developers on a whim without a standard still be painful

LOG_DIR=$1
TEMP_DIR=${LOG_DIR}/temp
REMOTE_HOST=filesv
REMOTE_FOLDER=/net/${REMOTE_HOST}/drbd/applog/applicationserver/`hostname`${1}
MONTHS_TO_KEEP=1  # months to keep log, the older ones will be archived. e.g: if current month is Sep, and month to keep is 1, the logs from August and older will be archived.

[[ ! -d $1 ]]&&{ echo "[ERROR] $1 not found";exit 1; }
[[ ! -d /net/${REMOTE_HOST} ]]&&{ echo "[ERROR] remote dir /net/${REMOTE_HOST} not found"; exit 1; }
[[ ! -d $TEMP_DIR ]]&&{ mkdir -p ${TEMP_DIR}; }   # Create temp folder if it doesn't exist
TIMELINE=$(date -d "$(date +%Y-%m-15) -$MONTHS_TO_KEEP months" +'%Y%m')

cd $LOG_DIR

# move all .gz files to temp dir if they 're available in LOG_DIR
find . -maxdepth 1 -type f -name "*.gz" -exec mv {} $TEMP_DIR/ \;

PATTERNS=$(ls -p | awk -F'[._-]20[0-9][0-9]|20[0-9][0-9]' '/.log/ {print $1}' | uniq | sed 's/\.log//' | grep -v /)
for PATTERN in $PATTERNS
do
 RETRY=$(ls $LOG_DIR/${PATTERN}* 2>/dev/null | wc -l) # Times of retry until exit from loop. This value is equal to the number of files with PATTERN in LOG_DIR. 
 OLDEST_TIME_STAMP=$(ls -p | grep -m1 "^${PATTERN}[._-]\{0,1\}\(log[._-]\)\{0,1\}20[0-9][0-9]" 2>/dev/null | sed "s/${PATTERN}//" | tr -cd '[:digit:]')
 if [[ ${#OLDEST_TIME_STAMP} -lt 8 ]]; then
  echo "[WARN] Timestamp extracted from file name $OLDEST_TIME_STAMP is invalid. Ignore pattern $PATTERN"
  continue
 fi
 RETRY_TIME=0
# while the 6 first characters of time stamp (e.g: 201607) is greater than current time
# and $RETRY_TIME is less than $RETRY
 while [[ "${OLDEST_TIME_STAMP}" ]]&&[[ ${OLDEST_TIME_STAMP:0:6} -le ${TIMELINE} ]]&&[[ $RETRY_TIME -lt $RETRY ]]
 do
# TIME_STAMP_PATTERN format: YYYY-mm
  YEAR=${OLDEST_TIME_STAMP:0:4}
  MONTH=${OLDEST_TIME_STAMP:4:2}
  TIME_STAMP_PATTERN=${YEAR}-${MONTH}
  echo "[INFO] Archiving ${PATTERN}_${TIME_STAMP_PATTERN}"
# files with PATTERN and TIME_STAMP_PATTERN
  LOG_FILES=$(find . -maxdepth 1 -type f -regextype sed -regex "\./${PATTERN}[-_.]\{0,1\}${YEAR}[-._]\{0,1\}${MONTH}.*" -or -regextype sed -regex "\./${PATTERN}.*[-_.]\{0,1\}${YEAR}[-_.]\{0,1\}${MONTH}.*")
# Check if log files is being used by any process
  fuser $LOG_FILES && {
    echo "[WARNING] There 're files being used. Abort archive ${PATTERN}_${TIME_STAMP_PATTERN}"
    RETRY_TIME=$(($RETRY_TIME + 1))
    continue
  }
  tar -cvzf ${TEMP_DIR}/${PATTERN}_${YEAR}-${MONTH}.tar.gz ${LOG_FILES} --remove-files
# Reset the OLDEST_TIME_STAMP variable
  OLDEST_TIME_STAMP=$(ls -p | grep -m1 "${PATTERN}[._-]\{0,1\}\(log[._-]\)\{0,1\}20[0-9][0-9]" 2>/dev/null | sed "s/${PATTERN}//" | tr -cd '[:digit:]')
  RETRY_TIME=$(($RETRY_TIME + 1)) # increase value of RETRY_TIME by 1
 done
done
# Exit if TEMP_DIR empty
[[ "$(ls -A $TEMP_DIR)" ]]||{ exit 0; }
# copy all archived file from TEMP_DIR to remote host
# and delete if copy is successful
mkdir -p $REMOTE_FOLDER && \
rsync -have --progress --backup --backup-dir=${REMOTE_FOLDER} --remove-source-files ${TEMP_DIR}/* ${REMOTE_FOLDER} && rmdir ${TEMP_DIR}

 

Simple monitoring – Chương trình monitor mạng đơn giản.

Chương trình được viết bằng python

Hướng dẫn cài đặt:

Cài đặt python3, và các gói cần thiết
yum install epel-release -y & yum install python36 python36-pip.noarch -y && pip3 install requests

Cách chạy app, sau khi thay cấu hình trong file config.py
cd <đường dẫn thư mục app>
python3 monitor_simple.py

Cách thiết lập chạy mỗi phút 1 lần:
crontab -l
Thêm vào dòng sau:
* * * * * /usr/bin/python3 <đường dẫn file monitor_simple.py>

Download:

https://github.com/khachuy2705/monitor_simple

Regular Expressions cơ bản

Cú pháp cơ bản:

.             1 ký tự bất kỳ, ngoại trừ xuống dòng
\.            dấu chấm (\ thể hiện escape)
\d            Một ký tự số
\D            Một ký tự không phải là số
\w            Một chữ hoặc số
\W            Một ký tự không phải là chữ
\s            một Dấu cách
\S            Một ký tự không phải dấu cách
\b            1 từ nguyên vẹn
\n            Xuống dòng
\t            Tab

Modifiers

$             Bắt đầu chuỗi
^             bắt đầu chuỗi
ab|cd         Matches ab hoặc cd.
[ab-d]	      Match a và match các ký tự từ b --> d = bcd
[^ab-d]	      One character except: a, b, c, d
()            Items within parenthesis are retrieved
(a(bc))       Items within the sub-parenthesis are retrieved

Repetitions

[ab]{2}       Exactly 2 continuous occurrences of a or b
[ab]{2,5}     2 to 5 continuous occurrences of a or b
[ab]{2,}      2 or more continuous occurrences of a or b
+             One or more
*             Zero or more
?             0 or 1

 

Xử lý lỗi cert SSL trên esxi

Case: Khi cài đặt Esxi ver 6.5. Một thanh niên cầu toàn, oder ngay 1 domain hịn, 1 SSL tương ứng để cắm lên ESXi với mục đích truy cập cho đỡ phải nhớ IP, và đã truy cập bẳng có ổ khoá xanh trên trình duyệt mới đã (Đừng hỏi tại sao lại public trang quản trị ESXi ra ngoài). Không may, up cái cert lỗi tè le lên, và thế là trang web quản trị chết toi luôn, telnet port 80, 443 thấy không thông nữa. làm gì đây:

Giải pháp: thay thế cert trên Esx bằng cert đúng

Bước 1: Truy cập vào màn hình console của ESXi bật SSH và ESX SHELL lên.

Bước 2: kiếm 1 máy tính  nào đó khác, sinh key RSA mới, ở đây chúng ta có 1 máy centos 7, đã cài sẵn openssl, sử dụng lệnh sau để sinh key:

openssl req -x509 -nodes -sha256 -days 1095 -newkey rsa:2048 -keyout rui.key -out rui.crt

Sau bước này sẽ sinh 2 file rui.key và rui.crt

Bước 4: SSH tới máy chủ ESXi, thư mục /etc/vmware/ssl và backup lại 2 file rui.key và rui.crt

# mv /etc/vmware/ssl/rui.crt /etc/vmware/ssl/rui.crt.bkp 
# mv /etc/vmware/ssl/rui.key /etc/vmware/ssl/rui.key.bkp

Bước 5: thay thế 2 file đã sinh ra ở bước 3, đưa vào đường dẫn /etc/vmware/ssl trên ESXi

Bước 6: Khởi động lại dịch vụ

cd
service.sh restart

Bước 7: Nghiệm thu

Sử dụng zabbix theo dõi thông tin metric của cluster hadoop

Yêu cầu:

  • Monitor đc các thông số cơ bản của cluster hadoop:
    • Số lượng app được submit
    • Số app đang chạy
    • Số app đang pending
    • Số memory: total, used
    • Số Vcore: Total, used
    • Node: số node, số node bị mất, số node có trạng thái unhealthy

Thực hiện:

  • Có thể xem các con số trên tại trang running custer của resource manager:

  • Ngoài ra, còn có thể sụng API để lấy các con số này:

Dưới đây là script thực hiện lấy các giá trị:

Apps Submitted
Apps Pending
Apps Running
Memory Used

Memory Total

VCores Used

VCores Total

Active Nodes

lostNodes

unhealthyNodes

totalNodes

Các giá trị này để gửi tới zabbix để xây dựng biểu đồ, và lưu trữ, thiết lập cảnh báo.

Dưới đây là script lấy số liệu:

#!/bin/bash
echo "appsSubmitted
appsPending

appsRunning

allocatedMB

totalMB

allocatedVirtualCores

totalVirtualCores

activeNodes

lostNodes

unhealthyNodes

totalNodes" > /tmp/readkey

curl -s -H "Content-Type: application/xml" http://c2s-spk06:8088/ws/v1/cluster/metrics http://c2s-spk07:8088/ws/v1/cluster/metrics > /tmp/input

IFS=$'\n'

for i in `cat /tmp/readkey`;do

a=`egrep -o "${i}\":[0-9]+" /tmp/input | awk -F':' '{print $2}'`

echo "$HOSTNAME yarn.metric.$i $a"

done

 

Output có dạng:

c2s-spk06 yarn.metric.appsSubmitted 443
c2s-spk06 yarn.metric.appsPending 0
c2s-spk06 yarn.metric.appsRunning 25
c2s-spk06 yarn.metric.allocatedMB 265216

c2s-spk06 yarn.metric.totalMB 307200

c2s-spk06 yarn.metric.allocatedVirtualCores 131

c2s-spk06 yarn.metric.totalVirtualCores 320

c2s-spk06 yarn.metric.activeNodes 5

c2s-spk06 yarn.metric.lostNodes 0

c2s-spk06 yarn.metric.unhealthyNodes 0

c2s-spk06 yarn.metric.totalNodes 5

Thiết lập đặt vào cron của máy hadoop, chạy 10 phút 1 lần, và đẩy output cho zabbix sender xử lý, gửi tới zabbix server, chi tiết cú pháp xem help của zabbix sender.

*/10 * * * * /bin/bash GetClusterMetricSpark.sh | /usr/local/zabbix/bin/zabbix_sender -i - -z ws-zbx

 

Xử lý lỗi KeyError khi ghép chuỗi python

Case:
chat_id=428519060
noidung='test'
body='''{"chat_id":"{}","text":"{}"}'''.format(chat_id,noi_dung)
KeyError: '"chat_id"'

Nguyên nhân: do sử dụng hàm format, nên trong chuỗi có dấu { hoặc } sẽ bị lỗi.
Xử lý: bằng cách thay { bằng {{ và } bằng }}
body='''{{"chat_id":"{}","text":"{}"}}'''.format(chat_id,noidung)
'{"chat_id":"428519060","text":"test"}'