ThaiTux.info - bash https://thaitux.info/taxonomy/term/96 bash: สคริปต์คัดลอกผู้ใช้ https://thaitux.info/node/755 <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>สคริปต์คัดลอกผู้ใช้จากระบบปัจจุบันไปยังไดเรคทอรี่ที่ติดตั้งลินุกซ์อีกตัวหนึ่ง<br /> มีประโยชน์สำหรับติดตั้งลินุกซ์หลายตัว และต้องการให้ผู้ใช้เหมือนกับระบบปัจจุบัน ตัวอย่างการใช้งานเช่น</p> <ul> <li>ติดตั้งลินุกซ์ผ่าน debootstrap</li> <li>ติดตั้งลินุกซ์โดยการเมานต์ live cd แล้วคัดลอก squashfs มาติดตั้งโดยตรง</li> </ul> <p>ข้อกำหนดคือ</p> <ul> <li>ต้องใช้สิทธิ์ root ในการรัน</li> <li>ต้องเป็นลินุกซ์ที่มีการเก็บไฟล์ผู้ใช้แบบมาตรฐาน คือเก็บที่ไฟล์ <code>/etc/passwd</code>, <code>/etc/group</code> และ <code>/etc/shadow</code></li> </ul> <p>สคริปต์มีดังนี้</p> <pre>$ <strong>sudo vi /usr/local/sbin/transfer_users.sh</strong></pre><pre>#!/bin/bash function usage() { cat &lt;&lt;EOF Usage: $0 DESTINATION Transfer users from current linux system to DESTINATION directory that have another linux system. Run as root. EOF exit 1 } DEST=$1 if [ ! "$UID" == "0" ]; then echo "Please run as root." usage fi if [ ! -d "$DEST" ]; then echo "DESTINATION directory not found." usage fi if [ ! -d "$DEST/etc" ]; then echo "DESTINATION/etc directory not found." usage fi US=`ls /home` TMP=/tmp/${RANDOM}.txt #SORT ON UID for i in $US; do UUID=`grep ":/home/${i}:" /etc/passwd | cut -d: -f3` echo "${UUID}:${i}" &gt;&gt; $TMP done #PROCESS EACH USER for i in `cat $TMP | sort`; do UUID=`echo $i | cut -d: -f1` U=`echo $i | cut -d: -f2` PASSWDLINE=`grep ":/home/${U}:" /etc/passwd` #/etc/group GNUM=`echo $PASSWDLINE | cut -d: -f4` GROUPLINE=`grep $GNUM /etc/group` GNAME=`echo $GROUPLINE | cut -d: -f1` OLDGROUP=`grep $GNAME $DEST/etc/group` if [ "$OLDGROUP" == "" ]; then echo $GROUPLINE &gt;&gt; $DEST/etc/group elif [ "$OLDGROUP" != "$GROUPLINE" ]; then sed -i "s/$OLDGROUP/$GROUPLINE/g" $DEST/etc/group fi #/etc/passwd OLDPASS=`grep ":/home/${U}:" $DEST/etc/passwd` if [ "$OLDPASS" == "" ]; then echo $PASSWDLINE &gt;&gt; $DEST/etc/passwd elif [ "$OLDPASS" != "$PASSWDLINE" ]; then sed -i "s/$OLDPASS/$PASSWDLINE/g" $DEST/etc/passwd fi #/etc/shadow SHADOWLINE=`grep "${U}:" /etc/shadow | grep -v '*'` OLDSHADOW=`grep "${U}:" $DEST/etc/shadow | grep -v '*'` if [ "$OLDSHADOW" == "" ]; then echo $SHADOWLINE &gt;&gt; $DEST/etc/shadow elif [ "$OLDSHADOW" != "$SHADOWLINE" ]; then sed -i "s#$OLDSHADOW#$SHADOWLINE#g" $DEST/etc/shadow fi #GROUP MEMBERS for j in `groups $U | cut -d: -f2`; do for k in `echo $j`; do if [ "$k" == "$GNAME" ]; then continue fi OLDLINE=`grep "${k}:" $DEST/etc/group` if ! echo $OLDLINE | grep $U ; then if [ "${OLDLINE: -1}" == ":" ]; then sed -i "s/$OLDLINE/${OLDLINE}${U}/g" $DEST/etc/group else sed -i "s/$OLDLINE/${OLDLINE},${U}/g" $DEST/etc/group fi fi done done #/HOME if [ ! -d "$DEST/home/$U" ]; then mkdir -p "$DEST/home/$U" fi chown -R ${U}:${GNAME} $DEST/home/$U done #for i in passwd group shadow; do # cp $DEST/etc/$i $DEST/etc/${i}- #done rm $TMP </pre><p> ตัวอย่างเช่น เราติดตั้งลินุกซ์อีกอันไว้ที่ <code>/dev/sdaXX</code></p> <pre>$ <strong>sudo mount /dev/sdaXX /mnt/tmp</strong> $ <strong>sudo /usr/local/sbin/transfer_users.sh /mnt/tmp</strong></pre><p> ผู้ใช้ทั้งหมดใน <code>/home/*</code> จะถูกคัดลอกไปยัง <code>/mnt/tmp/home/</code> ตามต้องการ</p> </div></div></div><div class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Topic:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/taxonomy/term/3">debian</a></div><div class="field-item odd"><a href="/taxonomy/term/96">bash</a></div></div></div> Thu, 19 Dec 2013 01:18:53 +0000 wd 755 at https://thaitux.info https://thaitux.info/node/755#comments bash: สคริปต์แก้ Boot record ของ NTFS https://thaitux.info/node/754 <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><h3>update 2556-12-03</h3> <p>ลองใช้สคริปต์กับพาร์ติชั่นที่ขนาดไม่เท่ากันแล้วปรากฎว่าใช้ไม่ได้ เพราะ NTFS เก็บข้อมูลหลายอย่างมากกว่าแค่จุดเริ่มต้นและขนาด (ดูที่ <a href="http://www.ntfs.com/ntfs-partition-boot-sector.htm">NTFS Partition Boot Sector</a>)</p> <p>วิธีที่ได้ผลกว่าคือ ฟอร์แมตไดร์ฟไว้ก่อน -> เก็บ boot sector ไว้ 72 ไบต์ -> ทำ ntfsclone -> เอา boot recort ที่เก็บไว้มาเขียนทับ</p> <p>ตัวอย่างเช่น จะคัดลอก ไดร์ฟ /dev/sda1 ไปยัง /dev/sdb1 ขั้นตอนจะเป็นดังนี้</p> <pre>$ <strong>sudo mkfs.ntfs -f /dev/sdb1</strong> $ <strong>sudo dd if=/dev/sdb1 of=sdb1.img bs=72 count=1</strong> $ <strong>sudo ntfsclone -O /dev/sdb1 /dev/sda1</strong> $ <strong>sudo dd if=sdb1.img of=/dev/sdb1</strong></pre><hr /> <p>*** สคริปต์ด้านล่างนี้ ล้าสมัยแล้ว ***</p> <p>แก้ปัญหาเวลาใช้ <a href="http://en.wikipedia.org/wiki/Ntfsprogs">ntfsclone</a> ในการ restore พาร์ติชั่น NTFS มาลงในฮาร์ดดิสก์ลูกใหม่ ซึ่งจุดเริ่มต้นและขนาดอาจไม่เท่าของเดิม</p> <p>วิธีการคือใช้ข้อมูลจากตาราง Master Boot Record ปัจจุบัน มาเขียนทับ boot record ของพาร์ติชั่น NTFS ที่ต้องการ โดยใช้เชลล์สคริปต์</p> <pre>$ <strong>vi ntfs_fix_boot_sector.sh</strong></pre><!--break--><pre> #!/bin/bash function usage() { cat &lt;&lt;EOF Fix NTFS boot record: Usage: $0 DEVICE Example: $0 /dev/sda1 EOF exit 1 } if [ ! "$1" ]; then usage fi PART=$1 if [ ! -b "$PART" ]; then echo -e "$PART not found. Exit.\n" usage fi BSF="`echo $PART | tr '/' '_'`.img" BSFB=${BSF}.bak BSFD="${BSF}_`date +%F`.bak" function reverse_byte () { #reverse_byte HEXSTR local S=$1 #HEXSTR local B local C while [ "$S" ]; do B=${S:(-2)} S=${S:0:-2} C="${C}\\x${B}" done echo $C } function replace_byte () { #replace_byte OFFSET LENGTH NUMBER local O=$1 #OFFSET local L=$2 #LENGTH local N=$3 #NUMBER let NL=${L}*2 XN=`printf "%0${NL}x" $N` RXN=`reverse_byte $XN` #echo "printf $RXN | dd of=$BSF bs=1 seek=$O count=$L conv=notrunc" printf $RXN | sudo dd of=$BSF bs=1 seek=$O count=$L conv=notrunc &gt; /dev/null 2&gt;&amp;1 } sudo dd if=$PART of=$BSF bs=512 count=1 &gt; /dev/null 2&gt;&amp;1 TMP="/tmp/$0_${RANDOM}.txt" HDD=$PART while [ "`echo ${HDD:(-1)} | tr '0123456789' ' '`" == " " ]; do HDD=${HDD:0:-1} done sudo fdisk -l $HDD &gt; $TMP if ! cat $TMP | grep $PART | grep NTFS &gt; /dev/null 2&gt;&amp;1; then echo -e "$PART is not NTFS partition. Exit.\n" sudo rm $TMP sudo rm $BSF usage fi if [ ! -f "$BSFB" ]; then cp $BSF $BSFB else cp $BSF $BSFD fi echo "Fixing $PART ..." HEADS=`cat $TMP | grep 'sectors/track' | cut -d, -f1 | cut -d\ -f1` SECTORS=`cat $TMP | grep 'sectors/track' | cut -d, -f2 | cut -d\ -f2` START=`cat $TMP | grep "${PART} " | awk -F' ' '{ print $2 }'` END=`cat $TMP | grep "${PART} " | awk -F' ' '{ print $4 }'` if [ "$START" == "*" ]; then START=`cat $TMP | grep "${PART} " | awk -F' ' '{ print $3 }'` END=`cat $TMP | grep "${PART} " | awk -F' ' '{ print $4 }'` fi let LENGTH=$END-$START OFFSET_HEADS=26 OFFSET_SECTORS=24 OFFSET_START=28 OFFSET_LENGTH=40 LEN_HEADS=1 LEN_SECTORS=1 LEN_START=4 LEN_LENGTH=4 for i in HEADS SECTORS START LENGTH; do A="OFFSET_${i}" B="LEN_${i}" replace_byte ${!A} ${!B} ${!i} done echo "Fix with heads=$HEADS, sectors/track=$SECTORS, start=$START, length=$LENGTH" sudo dd if=$BSF of=$PART &gt; /dev/null 2&gt;&amp;1 sudo rm $TMP cat &lt;&lt;EOF Command used: sudo dd if=$BSF of=$PART Revert with command: sudo dd if=$BSFB of=$PART EOF </pre><p> ตัวอย่าง สมมุติว่าพาร์ติชั่นที่ต้องการเป็น /dev/sda1 คำสั่งคือ</p> <pre>$ <strong>ntfs_fix_boot_record.sh /dev/sda1</strong></pre><p> ได้ผลลัพธ์คือ</p> <pre> Fixing /dev/sda1 ... Fix with heads=255, sectors/track=63, start=2048, length=62914559 Command used: sudo dd if=_dev_sda1.img of=/dev/sda1 Revert with command: sudo dd if=_dev_sda1.img.bak of=/dev/sda1 </pre><h3>ที่มา:</h3> <ul> <li><a href="http://www.2pi.info/software/copying-windows-new-hard-drive.html">Copying Windows to a New Hard Drive Using Linux</a></li> </ul> </div></div></div><div class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Topic:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/taxonomy/term/3">debian</a></div><div class="field-item odd"><a href="/taxonomy/term/75">ntfs</a></div><div class="field-item even"><a href="/taxonomy/term/96">bash</a></div></div></div> Tue, 26 Nov 2013 02:42:12 +0000 wd 754 at https://thaitux.info https://thaitux.info/node/754#comments bash: สคริปต์บล๊อกผู้ใช้ Drupal แบบอัตโนมัติ https://thaitux.info/node/753 <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>ปรับปรุงสคริปต์ให้สามารถบล๊อกโดยอัตโนมัติ</p> <pre>$ <strong>vi drupal_auto_blockuser.sh</strong></pre><!--break--><pre> #!/bin/bash # AUTO BLOCK DRUPAL USER SCRIPT, CHECK SPAM FROM google.co.th # FROM: https://drupal.org/node/118759 SITE=<em><strong>http://www.example.com</strong></em> # NO TRAILING SLASH NAME=<em><strong>drupal_admin_user</strong></em> PASS=<em><strong>drupal_admin_password</strong></em> UIDFILE=<em><strong>"site_last_uid.txt"</strong></em> SPAMDATA="spamdata.txt" SLEEP=10 #REDUCE SERVER LOAD STATUS=0 #0:block,1:unblock OPLOGIN="Log%20in" OPSUBMIT="Save" TMP=/tmp/$RANDOM.txt COOKIES=/tmp/$RANDOM.txt GGCOOKIES=/tmp/$RANDOM.txt AGENT="Mozilla/5.0 (X11; Linux x86_64; rv:25.0) Gecko/20130712 Firefox/25.0" QURL="https://www.google.co.th/search?q=" # LOGIN wget -q -o /dev/null -O /dev/null \ --keep-session-cookies --save-cookies $COOKIES --load-cookies $COOKIES \ --post-data="name=${NAME}&amp;pass=${PASS}&amp;op=${OPLOGIN}&amp;form_id=user_login" \ "${SITE}/?q=user/login" # PREVIOUS USER ID PREVUID=`cat $UIDFILE` let "STARTUID=${PREVUID}+1" # GET LAST USER ID wget -q -o /dev/null -O $TMP \ --keep-session-cookies --save-cookies $COOKIES --load-cookies $COOKIES \ "${SITE}/?q=admin/user/user" LASTUID=`grep -m1 'class="form-item" id="edit-accounts-' $TMP | awk -F'class="form-item" id="edit-accounts-' '{ print $2 }' | cut -d\- -f1` #DO CHECK for ID in `eval echo {$STARTUID..$LASTUID}`; do wget -q -o /dev/null -O $TMP \ --keep-session-cookies --save-cookies $COOKIES --load-cookies $COOKIES \ "${SITE}/?q=user/${ID}/edit" LINE0=`grep -n 'value="user_profile_form"' $TMP | cut -d: -f1` # PREVENT BLOCKED USER ERROR if ! [ "$LINE0" ]; then continue fi let "LINE=${LINE0}-1" TOKEN=`sed -n -e "${LINE}p" $TMP | awk -F'value="' '{ print $2 }' | cut -d\" -f1` USER1=`grep 'id="edit-name"' $TMP | awk -F'value="' '{ print $2 }' | cut -d\" -f1` EMAIL=`grep 'id="edit-mail"' $TMP | awk -F'value="' '{ print $2 }' | cut -d\" -f1` # QUERY FOR SPAM wget -q -o /dev/null -O $TMP \ --keep-session-cookies --save-cookies $GGCOOKIES --load-cookies $GGCOOKIES \ -U "$AGENT" "${QURL}${EMAIL}" ISSPAM=0 KEYWORD="" #*********************** ### BEWARE THIS WHILE LOOP, VARIABLE $ISSPAM IS LOCAL, USE REDIRECT INSTEAD OF PIPE ### #cat $SPAMDATA | while read TXT; do # if [ "$TXT" ]; then # if grep -m1 "$TXT" $TMP &gt; /dev/null; then # ISSPAM=1 # break # fi # fi #done #*********************** while read TXT; do if [ "$TXT" ]; then if grep -m1 "$TXT" $TMP &gt; /dev/null; then ISSPAM=1 KEYWORD=$TXT break fi fi done &lt; &lt;(cat $SPAMDATA ) if [ "$ISSPAM" != "0" ]; then #DO BLOCK wget -q -o /dev/null -O /dev/null \ --keep-session-cookies --save-cookies $COOKIES --load-cookies $COOKIES \ --post-data="status=${STATUS}&amp;op=${OPSUBMIT}&amp;name=${USER1}&amp;mail=${EMAIL}&amp;form_token=${TOKEN}&amp;form_id=user_profile_form" \ "${SITE}/?q=user/${ID}/edit" echo "UID:\"$ID\", USER:\"$USER1\", EMAIL:\"$EMAIL\", KEYWORD:\"$KEYWORD\" --- Blocked." sleep $SLEEP else echo "--- UID:\"$ID\", USER:\"$USER1\", EMAIL:\"$EMAIL\", not found as spam." fi sleep $SLEEP done # SAVE LAST UID echo $LASTUID &gt; $UIDFILE rm $TMP rm $COOKIES rm $GGCOOKIES </pre><pre>$ <strong>chmod 700 drupal_auto_blockuser.sh</strong></pre><h4>สร้างไฟล์ spamdata.txt</h4> <p>ใส่ค่า spam keyword</p> <pre>$ <strong>vi spamdata.txt</strong></pre><pre> did not match any documents Spam ไม่ตรงกับเอกสารใด </pre><h4>สร้างไฟล์ site_last_uid.txt</h4> <p>ใส่ค่า uid ของผู้ใช้คนสุดท้ายที่ไม่ต้องการตรวจ (สมมุติว่าเป็นผู้ใช้คนที่ 1000)</p> <pre>$ <strong>vi site_last_uid.txt</strong></pre><pre> 1000</pre><h4>รัน</h4> <pre>$ <strong>./drupal_auto_blockuser.sh</strong></pre><p> ครั้งต่อไปก็แค่สั่งรัน โดยไม่ต้องปรับแต่งอะไรอีก เว้นแต่มี spam keyword เพิ่มเติมก็ไปแก้ไฟล์ spamdata.txt</p> <h4>ปรับปรุง</h4> <ul> <li>เพิ่ม cookies ให้กับ google เพื่อไม่ให้ google คิดว่าเป็น bot</li> </ul> </div></div></div><div class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Topic:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/taxonomy/term/18">drupal</a></div><div class="field-item odd"><a href="/taxonomy/term/96">bash</a></div></div></div> Sat, 13 Jul 2013 10:24:27 +0000 wd 753 at https://thaitux.info https://thaitux.info/node/753#comments bash: สคริปต์บล๊อกผู้ใช้ Drupal https://thaitux.info/node/752 <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>ทำสคริปต์บล๊อกผู้ใช้ <a href="https://drupal.org">Drupal</a> จากบรรทัดคำสั่ง (bash)</p> <pre>$ <strong>vi drupal_blockuser.sh</strong></pre><!--break--><pre> #!/bin/bash #FROM: https://drupal.org/node/118759 if [ "$#" == "0" ]; then echo "Script to block drupal users by uid" echo "Usage: $0 UID1 UID2 UID3 ..." exit 1 fi SITE=<strong><em>http://www.example.com</em></strong> #NO END SLASH NAME=<strong><em>drupal_admin_user</em></strong> PASS=<strong><em>drupal_admin_password</em></strong> STATUS=0 #0:block,1:unblock OPLOGIN="Log%20in" OPSUBMIT="Save" TMP=/tmp/$RANDOM.txt COOKIES=/tmp/$RANDOM.txt #LOGIN wget -q -o /dev/null -O /dev/null \ --keep-session-cookies --save-cookies $COOKIES --load-cookies $COOKIES \ --post-data="name=${NAME}&amp;pass=${PASS}&amp;op=${OPLOGIN}&amp;form_id=user_login" \ "${SITE}/?q=user/login" #DO BLOCK while (( "$#" )); do ID=$1 wget -q -o /dev/null -O $TMP \ --keep-session-cookies --save-cookies $COOKIES --load-cookies $COOKIES \ "${SITE}/?q=user/${ID}/edit" let "LINE=`grep -n 'value="user_profile_form"' $TMP | cut -d: -f1`-1" TOKEN=`sed -n -e "${LINE}p" $TMP | awk -F'value="' '{ print $2 }' | cut -d\" -f1` USER1=`grep 'id="edit-name"' $TMP | awk -F'value="' '{ print $2 }' | cut -d\" -f1` EMAIL=`grep 'id="edit-mail"' $TMP | awk -F'value="' '{ print $2 }' | cut -d\" -f1` wget -q -o /dev/null -O /dev/null \ --keep-session-cookies --save-cookies $COOKIES --load-cookies $COOKIES \ --post-data="status=${STATUS}&amp;op=${OPSUBMIT}&amp;name=${USER1}&amp;mail=${EMAIL}&amp;form_token=${TOKEN}&amp;form_id=user_profile_form" \ "${SITE}/?q=user/${ID}/edit" echo "USER:\"$USER1\" --- EMAIL:\"$EMAIL\" --- Blocked." shift done rm $TMP rm $COOKIES </pre><pre>$ <strong>chmod 700 ./drupal_blockuser.sh</strong></pre><p> วิธีใช้งานก็สั่ง</p> <pre>$ <strong>./drupal_blockuser.sh <em>UID1 UID2 UID3 ...</em></strong></pre><p> อย่าลืมแก้ตัวแปร <code>SITE, NAME, PASS</code> ให้เข้ากับงานเรา</p> </div></div></div><div class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Topic:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/taxonomy/term/18">drupal</a></div><div class="field-item odd"><a href="/taxonomy/term/96">bash</a></div></div></div> Sat, 13 Jul 2013 07:08:49 +0000 wd 752 at https://thaitux.info https://thaitux.info/node/752#comments bash script: แบ่งไฟล์สื่อออกเป็นหลาย ๆ ส่วน https://thaitux.info/node/699 <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>เห็น<a href="http://forum.ubuntuclub.com/forum/topic,17074.0.html">คำถามเกี่ยวกับการแบ่งไฟล์สื่อออกเป็นหลายส่วนที่ ubuntuclub.com</a><br /> ด้วยต้องการคลายเครียด จึงวางแผนลงมือเขียนสคริปต์ โดยคิดให้สคริปต์มีการทำงานดังต่อไปนี้</p> <ol> <li>หาความยาวสื่อ ด้วยโปรแกรม ffmpeg ด้วยคำสั่ง<br /> <pre>ffmpeg -i "$INFILE" 2&gt;&amp;1 | grep "Duration" | cut -d ' ' -f 4 | sed s/,//</pre></li> <li>หาความยาวแต่ละส่วน (ความยาวสื่อ ÷ จำนวนส่วนที่จะแยก)</li> <li>ใช้ mencoder มาตัดส่วน -ss คือ seek ไปยังตำแหน่ง, -endpos คือให้ประมวลผลเท่าใด (เป็นขนาดก็ได้ เป็นจำนวนเฟรมก็ได้ เป็นค่าเวลาก็ได้)</li> </ol> <p>เสร็จแล้วเขียนออกมาหยาบ ๆ และทดสอบไปเล็กน้อยว่าใช้งานได้จริงแล้วเลยเอามาบันทึกไว้กันลืมเสียหน่อย</p> <p>โดยผลลัพธ์ที่ได้ออกมาเป็นสคริปต์ sep_media.sh เป็นดังนี้:</p> <p><b>sep_media.sh:</b></p> <pre> <i><b>#!/bin/bash</b> # # Script for separate media file by MENCoder # by Thanomsub Noppaburana &lt;donga.nb@gmail.com&gt; # Usage: sep_media.sh # Example: # For separate Doraemon.avi into 20 parts with prefix "Doraemon_Part" # sep_media.sh Doraemon.avi Doraemon_Part 20 #</i> INFILE="$1" OUTFILEPREFIX="$2" TOTALPART="$3" EXTENSION="" [ ! -z "$INFILE" ] &amp;&amp; EXTENSION="`echo "$INFILE" | awk -F . '{print $NF}'`" <i>## ----------------------------------------------------------------- ## ## functions declaration ## ----------------------------------------------------------------- ##</i> <b>usage()</b> { echo echo -e "Usage:" echo -e "\t`basename $0` " echo -e "Example:" echo -e "\tFor separate Doraemon.avi into 20 parts with prefix \"Doraemon_Part\"" echo -e "\tsep_media.sh Doraemon.avi Doraemon_Part 20" echo } <b>getTotalLength()</b> { echo `ffmpeg -i "$INFILE" 2&gt;&amp;1 | grep "Duration" | cut -d ' ' -f 4 | sed s/,// | awk -F: '{ print ($1*3600)+($2*60)+$3 }'` } <b>getEachPartLength()</b> { echo $1:$2 | awk -F: '{ print $1/$2 }' } <b>separateMedia()</b> { TOTALPART=$1 TOTALLENGTH=$2 EACHPARTLENGTH=$3 for ((i=0;i&lt;$TOTALPART;i++)) do STARTPOS=`echo $i $EACHPARTLENGTH | awk '{print ($1*$2)+0.01}'` echo "=====================================================================================================" echo " Separating media part $i: $OUTFILEPREFIX$i.$EXTENSION : " echo "-----------------------------------------------------------------------------------------------------" mencoder -of lavf -oac copy -ovc copy -o $OUTFILEPREFIX$i.$EXTENSION -ss $STARTPOS -endpos $EACHPARTLENGTH $INFILE echo "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" done } <i>## ----------------------------------------------------------------- ## ## main program ## ----------------------------------------------------------------- ##</i> if [ -z "$INFILE" -o -z "$OUTFILEPREFIX" -o -z "$TOTALPART" ]; then usage exit 0 fi TOTALLENGTH=`getTotalLength` EACHPARTLENGTH=`getEachPartLength $TOTALLENGTH $TOTALPART` separateMedia $TOTALPART $TOTALLENGTH $EACHPARTLENGTH </pre><h3>วิธีใช้งาน:</h3> <p>ตัวอย่างเช่น ต้องการแยก Doraemon.avi เป็น 20 ส่วน โดยให้ไฟล์ที่โดนแยกนำหน้าด้วยชื่อ "Doraemon_Part"</p> <pre>sep_media.sh Doraemon.avi Doraemon_Part 20</pre><p>ซึ่งก็จะได้ผลลัพธ์เป็นแฟ้ม Doraemon_Part0.avi ถึง Doraemon_Part19.avi ออกมา เป็นต้น</p> <h3>ดาวน์โหลด:</h3> <p>ผู้สนใจสามารถดาวน์โหลดไปใช้ได้เลยครับ <a href="http://www.fileden.com/files/2010/2/18/2766294/sep_media.sh">ดาวน์โหลดสคริปต์ sep_media.sh</a><br /> จากนั้นเซฟไว้ใน search path และอย่าลืมตั้ง permission ให้ประมวลผลได้ก่อน ด้วยคำสั่ง</p> <pre>sudo chmod ugo+x /path/to/sep_media.sh</pre><p>เป็นอันพร้อมใช้งานครับ ^_^</p> </div></div></div><div class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Topic:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/taxonomy/term/46">multimedia</a></div><div class="field-item odd"><a href="/taxonomy/term/96">bash</a></div><div class="field-item even"><a href="/taxonomy/term/97">tip</a></div></div></div> Tue, 10 Aug 2010 06:34:01 +0000 donga 699 at https://thaitux.info https://thaitux.info/node/699#comments bash: Rip audio disc to mp3 https://thaitux.info/node/532 <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even">มีงานต้องเก็บแผ่นซีดีธรรมะลงไว้ในฮาร์ดดิสก์เป็นจำนวนมาก<br /> เพื่อให้สะดวก จึงทำเป็นสคริปต์ให้ใช้งานได้สะดวก<br /> ลักษณะของโปรแกรมคือ เมื่อเราใส่แผ่นแล้วสั่งรันโปรแกรม เขาจะถอดไฟล์เสียงทั้งหมดมาเป็นไฟล์ mp3 ที่ไดเรกทอรี่ปัจจุบัน โดยเอาข้อมูลชื่อเพลงจากแผ่นมาเป็นชื่อไฟล์ ก่อนอื่นติดตั้งแพกเกจที่จำเป็นก่อน<br /> <code>$ sudo aptitude install lame cdda2wav</code> สคริปต์มีดังนี้<br /> <code>$ sudo vi /usr/local/bin/d.audio2mp3</code> <pre lang="bash" xml:lang="bash">#!/bin/bash # Rip audio disc to mp3 # # USAGE: $0 prefix # exam1: $0 T2 # -&gt; T2-01-Title1.mp3 # T2-02-Title2.mp3 # ... # in current dir # # Requist: aptitude install lame cdda2wav if [ $1 ]; then PREFIX="$1-"; fi DEV='/dev/cdrom' TMP="/tmp/$USER/`basename $0`_$RANDOM" mkdir -p $TMP pushd $TMP #to wave cdda2wav -L 1 -D $DEV -B #to mp3 for i in *wav; do NUM=`echo ${i%.*} | cut -d_ -f 2`- TITLE=`grep 'Tracktitle=' ${i%.*}.inf | cut -d\' -f2` lame -h -V 2 $i $PREFIX$NUM$TITLE.mp3 done popd mv $TMP/*mp3 . rm -rf $TMP </pre> ทำให้รันได้<br /> <code>$ sudo chmod 777 /usr/local/bin/d.audio2mp3</code> เสร็จแล้ว<br /> การใช้งานคือ ใส่แผ่น audio แล้วสั่งรัน d.audio2mp3 จะได้ไฟล์ mp3 มาอยู่ในไดเรคทอรี่ปัจจุบัน การทำงานของสคริปต์คือ <ul> <li>แปลงข้อมูลเสียงมาเป็นไฟล์ wav ด้วยโปรแกรม cdda2wav โดยนำไปใส่ในไดเรคทอรี่ชั่วคราวใน /tmp (เพื่อป้องกันผู้ใช้หลายคน จึงใส่ตัวแปร $USER ไว้ด้วย เพราะโค๊ดต้นฉบับ เขียนบนเซิร์ฟเวอร์ที่มีผู้ใช้หลายคน)</li> <li>แปลงไฟล์ wav ที่ได้มาเป็น mp3 โดยใช้โปรแกรม lame (ซึ่งอาจมีปัญหาว่าตอนนี้หา lame บน lenny กับ sid ไม่ได้แล้ว ให้ลองดูวิธีปรุงขึ้นมาเองได้ที่ <a href="http://thisk.org/dr/node/32">วิธีปรุง lame โดยคุณโดม http://thisk.org/dr/node/32</a>)<br /> โดยเอาข้อมูล Tracktitle จากไฟล์นามสกุล inf มาเป็นชื่อไฟล์ mp3 ที่ได้ รวมถึงใส่คำนำหน้า (ตัวแปร $PREFIX) ให้ด้วย</li> </ul> <h3>update</h3> <ul> <li><strong>25570325</strong>: แพ็กเกจเปลี่ยน ไม่ต้องใช้สคริปต์แล้ว เพียงลงแพ็กเกจชื่อ <code>icedax</code> แล้วใช้คำสั่ง<br /> <pre>$ <strong>CDDA_DEVICE=/dev/sr0 cdda2mp3</strong></pre></li> </ul></div></div></div><div class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Topic:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/taxonomy/term/96">bash</a></div><div class="field-item odd"><a href="/taxonomy/term/159">mp3</a></div><div class="field-item even"><a href="/taxonomy/term/304">audio</a></div></div></div> Wed, 24 Sep 2008 03:22:48 +0000 wd 532 at https://thaitux.info https://thaitux.info/node/532#comments bash: ทำบัตรเลขที่ https://thaitux.info/node/524 <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even">มีโจทย์คือ ให้สร้างบัตรแบบเรียงเลขที่ ตั้งแต่ ๑ จนถึง ๕๐๐<br /> ตัดสินใจใช้ <code>bash + inkscape</code> เพราะง่ายดี<br /> โดยสมมุติว่าเราได้สร้างเอกสารเป็นไฟล์ inkscape ไว้แล้ว โดยให้ตัวเลขที่จะเรียงให้มีค่าเป็น <code>XXXX</code> เพื่อให้สะดวกในการใช้คำสั่ง <code>grep</code> โค๊ดที่สร้างขึ้น ทำแบบง่าย ๆ คือรันตัวเลขตั้งแต่ 1-500 แต่รุ่นนี้เป็นรุ่นทดสอบ ทำแค่ 1-10 พอ ขั้นตอนคือ <ul> <li>แปลงตัวเลขเป็นเลขไทย ด้วยคำสั่ง <code>awk</code></li> <li>นำไปแทนที่ในไฟล์ inkscape แล้วทำออกมาเป็นไฟล์ใหม่ ด้วยคำสั่ง <code>sed</code></li> <li>แล้วสั่งส่งออกมาเป็นไฟล์นามสกุล <code>png</code> ด้วยคำสั่งแบบบรรทัดคำสั่งของ <code>inkscape</code> เอง ด้วยพารามิเตอร์ <code>-e</code></li> </ul> โค๊ดมีดังนี้ <pre lang="bash" xml:lang="bash">$ <strong>vi runcard</strong></pre><pre lang="bash" xml:lang="bash">#!/bin/bash FILE='card.svg' QUAN=10 MARKER='XXXX' for i in $(seq 1 $QUAN); do TNUM=`echo $i | awk '{ gsub ("0","๐"); gsub ("1","๑"); gsub ("2","๒"); gsub ("3","๓"); gsub ("4","๔"); gsub ("5","๕"); gsub ("6","๖"); gsub ("7","๗"); gsub ("8","๘"); gsub ("9","๙"); print }'` sed -e "s/$MARKER/$TNUM/g" $FILE &gt; tmp.svg inkscape -d 300 -e tmp$i.png tmp.svg done </pre><pre lang="bash" xml:lang="bash">$ <strong>chmod 755 runcard</strong></pre> เวลาใช้งานก็สั่งรันชื่อไฟล์ <code>runcard</code> เฉย ๆ จะได้ไฟล์ tmp1.png จนถึง tmp10.png ก็สามารถนำไฟล์เหล่านี้ไปพิมพ์งานได้ตามต้องการ <img src="http://farm4.static.flickr.com/3153/2789183714_5c9b1bf70a.jpg" /></div></div></div><div class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Topic:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/taxonomy/term/96">bash</a></div><div class="field-item odd"><a href="/taxonomy/term/301">awk</a></div></div></div> Sat, 23 Aug 2008 08:30:38 +0000 wd 524 at https://thaitux.info https://thaitux.info/node/524#comments bash: ลองทำ cron ตรวจ apt-proxy https://thaitux.info/node/495 <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even">แพกเกจ <a href="http://apt-proxy.sourceforge.net/">apt-proxy</a> เป็นแพกเกจที่ใช้เป็นคลังเก็บแพกเกจที่เครือข่ายเราใช้ประจำ ใช้ง่ายและสะดวก แต่ชอบตายบ่อย จะเข้าไปรื้อดูการทำงาน ก็ยากเกินความสามารถ เลยลองเขียนเป็น cron แก้ปัญหาเฉพาะหน้าไปก่อน การทำงานของสคริปต์ก็ไม่มีอะไรมาก แค่ตรวจว่าการใช้คำสั่ง aptitude update นานเกิน 60 วินาทีหรือไม่ ถ้านานก็ให้เริ่ม apt-proxy ใหม่ แค่นี้เอง<br /> (สามารถปรับช่วงเวลารอที่ตัวแปร <code>TIME_WAIT</code> ตามความเร็วของเน็ตที่มีอยู่จริง) <code># vi /usr/local/sbin/d.cron-check-apt-proxy</code> <pre lang="bash" xml:lang="bash">#!/bin/bash TIME_WAIT='60' function sub_wait() { sleep $TIME_WAIT echo `date +%F-%R-%s` } function update_apt_proxy() { aptitude update echo `date +%F-%R-%s` } T1=`sub_wait` &amp; T2=`update_apt_proxy` &amp; wait if [ "$T1" \&lt; "$T2" ]; then echo "apt-proxy update longer than $TIME_WAIT seconds, restart apt-proxy." /etc/init.d/apt-proxy restart fi </pre><code># chmod 755 /usr/local/bin/d.cron-check-apt-proxy</code> ตั้ง crontab ให้รันทุกชั่วโมง<br /> <code># crontab -e</code> <pre>... #CHECK apt-proxy EVERY 60 MIN 0 * * * * /usr/local/sbin/d.cron-check-apt-proxy ...</pre> เสร็จแล้ว ลองใช้ดูก่อน แล้วจะรายงานผลต่อไปตรับ <strong>update</strong> <ul> <li>เจอสาเหตุแล้ว มาจากตั้ง squid3 เป็นแบบ transparent ไว้ ทางแก้คือ ยกเลิก transparent หรือไม่ก็ปรับ apt-proxy ให้ไปใช้ http_proxy ที่พอร์ต 8080 (หรือพอร์ตอื่นที่ตั้งไว้ใน squid) เรียบร้อยแล้ว - แต่สคริปต์นี้ก็ยังน่าใช้อยู่ดี อาจปรับเป็นทุก 3 ชั่วโมงก็ได้</li> </ul></div></div></div><div class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Topic:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/taxonomy/term/96">bash</a></div><div class="field-item odd"><a href="/taxonomy/term/130">apt-proxy</a></div></div></div> Fri, 07 Mar 2008 09:25:36 +0000 wd 495 at https://thaitux.info https://thaitux.info/node/495#comments bash: ย้ายข้อมูลผู้ใช้ไปเครื่องใหม่ https://thaitux.info/node/489 <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>ต้องการโอนข้อมูลผู้ใช้ไปเครื่องใหม่</p> <p>ถ้าเราคัดลอกไฟล์ <code>/etc/passwd /etc/shadow /etc/group /etc/gshadow</code> ไปทับเครื่องใหม่แบบตรง ๆ จะเกิดปัญหาเรื่องผู้ใช้ของระบบจะติดไปด้วย ซึ่งอาจมีค่า UID และ GID ที่ไม่ตรงกัน</p> <p>ค้นกูเกิลได้วิธีการจากที่นี่ครับ <a href="http://www.cyberciti.biz/faq/howto-move-migrate-user-accounts-old-to-new-server/">Move or migrate user accounts from old Linux server to a new Linux server</a></p> <p>เขาใช้หลักการที่ว่า UID ของผู้ใช้ทั่วไป จะมีค่ามากกว่า 1000 (ของ RedHat คือ 500)<br /> และใช้ <code>awk</code> เป็นตัวกรอง</p> <p><strong>--- ข้อเขียนต่อจากนี้ไป ควรทดสอบกับเครื่องทดสอบ ก่อนใช้งานจริง---</strong></p> <p>ขั้นตอนตามต้นฉบับก็ไม่มากเท่าไหร่ แต่กลัวว่าเวลาย้ายจริงจะพิมพ์พลาด เลยเอามาเขียนเป็นสคริปต์เพื่อช่วยลดความผิดพลาดตอนพิมพ์บนบรรทัดคำสั่ง รวมทั้งเป็นการศึกษาการเขียนสคริปต์ของ <code>bash</code> ร่วมกันแล้วกันนะครับ</p> <p>ตั้งชื่อว่า <code>d.migrate-groupuser</code> ผมใส่ไว้ใน <code>/root</code><br /> (ห้ามใส่ในพาธการค้นหาของระบบเด็ดขาด เพราะต้องมีการแก้ไขค่าก่อนใช้งานจริง)</p> <p>ตอนใช้งานก็เปลี่ยนค่าตัวแปร <code>TARGETMACHINE</code> ให้เป็นชื่อเครื่องใหม่ที่เราจะโอนไป แล้วก็สั่งรันได้เลย</p> <p>โปรแกรมจะทำงานดังนี้</p> <ol> <li>คัดลอกไฟล์ <code>/etc/{passwd,shadow,group,gshadow}</code> และบีบอัดไดเรกทอรี่ <code>/home</code> และ <code>/var/spool/mail</code> มาไว้ในไดเรกทอรี่ <code>$MIGRATEDIR</code></li> <li>ผลิตสคริปต์ชื่อ d.import-groupuser</code> เอาไว้สั่งรันที่เครื่องใหม่ และ <code>d.rollback-groupuser</code> เอาไว้สั่งทำย้อนกลับที่เครื่องใหม่เช่นกัน</li> <li>โอนไฟล์ทั้งหมดใน <code>$MIGRATEDIR</code> ไปยังเครื่องใหม่</li> </ol> <p>หลังจากนั้น เราก็สั่งรันสคริปต์ <code>d.import-groupuser</code> ที่เครื่องใหม่ได้เลย</p> <p><strong>*** ใช้ด้วยความระมัดระวัง ***</strong></p> <p>เริ่มเลย<br /> <code># vi /root/d.migrate-groupuser</code></p> <pre> #!/bin/bash #PREREQUISITE: # 1. INSTALL PACKAGE: openssh-client # 2. EDIT THIS FILE, CHANGE VARIABLE "TARGETMACHINE" TO REAL TARGET #THEN RUN AS root MIGRATEDIR="/root/migrategroupuser" #MIGRATE DIR UGIDLIMIT=1000 #UID&amp;GID OF USER DATA: DEBIAN=1000, REDHAT=500 # EDIT TARGETMACHINE TARGETMACHINE="newserver" #COPY TO THIS MACHINE TARGETDIR="/root/importgroupuser" #COPY DATA TO THIS DIR if [ "$1" != "OK" ]; then PROG=`basename $0` cat &lt;&lt; EOF *** DON'T PLACE THIS SCRIPT IN SYSTEM SEARCH PATH *** USE WITH CARE *** EDIT TARGETMACHINE VARIABLE THEN RUN AS ROOT Move or migrate user accounts from old Linux server to a new Linux server FROM: http://www.cyberciti.biz/faq/howto-move-migrate-user-accounts-old-to-new-server/ USE WITH CARE, PLEASE BACKUP OLD DATA, RUN AS ROOT - COPY FILTERED /etc/{passwd,group,shadow,gshadow} TO $MIGRATEDIR WITH EXT .mig - BACKUP /home, /var/spool/mail TO $MIGRATEDIR .tar.gz - TRANSFER ALL FILES IN $MIGRATEDIR TO root@$TARGETMACHINE:$TARGETDIR WITH scp USAGE: $PROG OK ('OK' is safety argument) DON'T FORGET TO EDIT TARGETMACHINE VARIABLES EOF exit 1 fi if [ ! `which scp` ]; then echo "Please install 'openssh-client' first." exit 1 fi mkdir -p $MIGRATEDIR echo " Copy /etc/{password,group,shadow,gshadow} to $MIGRATEDIR ..." for i in /etc/{passwd,group,shadow,gshadow}; do j=`basename $i` awk -v LIMIT=$UGIDLIMIT -F: '($3&gt;=LIMIT) &amp;&amp; ($3!=65534)' $i &gt; $MIGRATEDIR/$j.mig done echo " gzip /home ..." tar -zcpf $MIGRATEDIR/home.tar.gz /home/* echo " gzip /var/spool/mail ..." tar -zcpf $MIGRATEDIR/mail.tar.gz /var/spool/mail/* #------------------------------------------------ echo " Generate import script ..." IMPORTPROG="d.import-groupuser" cat &gt; $MIGRATEDIR/$IMPORTPROG &lt;&lt; VIRTUAL_EOF #!/bin/bash IMPORTDIR="/root/importgroupuser" #COPY DATA TO THIS DIR BACKUPDIR="/root/backupgroupuser" #BACKUP OLD DATA if [ "\$1" != "OK" ]; then PROG=\`basename \$0\` cat &lt;&lt; EOF Move or migrate user accounts from old Linux server to a new Linux server FROM: http://www.cyberciti.biz/faq/howto-move-migrate-user-accounts-old-to-new-server/ USE WITH CARE, PLEASE BACKUP OLD DATA, RUN AS ROOT - BACKUP /etc/{passwd,group,shadow,gshadow} TO \$BACKUPDIR/etc - BACKUP /home /var/spool/mail TO \$BACKUPDIR/tar - ADD NEW GROUP-USER DATA FROM \$IMPORTDIR TO /etc - ADD NEW /home AND /var/spool/mail TO / USAGE: \$PROG OK ('OK' is safety argument.) EOF exit 1 fi if [ ! -d \$IMPORTDIR ]; then echo "\$IMPORTDIR not exist, program aborted" exit 1 fi echo " Backup old data and add migrate data to /etc/{passwd,group,shadow,gshadow} ..." mkdir -p \$BACKUPDIR pushd \$BACKUPDIR ls | while read FILE; do mv "\$FILE" "\$FILE.bak" done mkdir -p {etc,tar} for i in {passwd,group,shadow,gshadow}; do cp /etc/\$i etc cat \$IMPORTDIR/\$i.mig &gt;&gt; /etc/\$i done echo " Backup /home and /var/spool/mail in \$BACKUPDIR/tar ..." tar -zcpf tar/home.tar.gz /home/* tar -zcpf tar/mail.tar.gz /var/spool/mail/* popd echo " Extract imported data in \$IMPORTDIR to /home and /var/spool/mail ..." pushd / echo " gunzip \$IMPORTDIR/home.tar.gz to / ..." tar -zxf \$IMPORTDIR/home.tar.gz echo " gunzip \$IMPORTDIR/mail.tar.gz to / ..." tar -zxf \$IMPORTDIR/mail.tar.gz popd echo " Import finished." echo echo "Please delete these files to finish the work:" echo " \$BACKUPDIR" echo " \$IMPORTDIR/d.import-groupuser" echo " \$IMPORTDIR/d.rollback-groupuser" echo VIRTUAL_EOF chmod 700 $MIGRATEDIR/$IMPORTPROG #------------------------------------------------ echo "Generate rollback script ..." ROLLBACKPROG="d.rollback-groupuser" cat &gt; $MIGRATEDIR/$ROLLBACKPROG &lt;&lt; VIRTUAL_EOF #!/bin/bash BACKUPDIR="/root/backupgroupuser" #BACKUP OLD DATA if [ "\$1" != "OK" ]; then PROG=\`basename $0\` cat &lt;&lt; EOF Move or migrate user accounts from old Linux server to a new Linux server FROM: http://www.cyberciti.biz/faq/howto-move-migrate-user-accounts-old-to-new-server/ USE WITH CARE, PLEASE BACKUP OLD DATA, RUN AS ROOT, NO WARNING - COPY BACKUP DATA IN \$BACKUPDIR/etc TO /etc - *** REMOVE OLD /home AND /var/spool/mail *** - COPY BACKUP DATA IN \$BACKUPDIR/tar TO /home and /var/spool/mail - ROLLBACK \$BACKUPDIR/*.bak USAGE: \$PROG OK ('OK' is safety argument.) EOF exit 1 fi if [ ! -d \$BACKUPDIR/etc ]; then echo "\$BACKUPDIR/etc not exist, program aborted" exit 1 fi if [ ! -d \$BACKUPDIR/tar ]; then echo "\$BACKUPDIR/tar not exist, program aborted" exit 1 fi echo " Copy \$BACKUPDIR/etc to /etc ..." pushd \$BACKUPDIR cp etc/* /etc popd echo " *** Remove /home and /var/spool/mail *** ..." rm -rf /home /var/spool/mail echo " Copy \$BACKUPDIR/tar to /home and /var/spool/mail ..." pushd / tar -zxf \$BACKUPDIR/tar/home.tar.gz tar -zxf \$BACKUPDIR/tar/mail.tar.gz popd echo " Remove last rollback data ..." pushd \$BACKUPDIR rm -rf etc tar for i in *.bak; do mv \$i \${i%.bak} done echo " Rollback finished." VIRTUAL_EOF chmod 700 $MIGRATEDIR/$ROLLBACKPROG #------------------------------------------------ echo " Transfer data to root@$TARGETMACHINE:$TARGETDIR, enter $TARGETMACHINE root password:" echo "COMMAND RUN: scp -r $MIGRATEDIR root@$TARGETMACHINE:$TARGETDIR" scp -r $MIGRATEDIR/* root@$TARGETMACHINE:$TARGETDIR echo " Finished. Next, run $MIGRATEDIR/$IMPORTPROG at $TARGETMACHINE (*** Use $ROLLBACKPROG to undo the job, BUT DO USE WITH CARE ***) " </pre><p> เปลี่ยนสถานะให้รันได้<br /> <code># chmod 700 /root/d.migrate-groupuser</code></p> <p>ทดลองรัน<br /> เริ่มที่เครื่องเก่า<br /> <code># /root/d.migrate-groupuser OK</code></p> <pre> Copy /etc/{password,group,shadow,gshadow} to /root/migrategroupuser ... gzip /home ... tar: Removing leading `/' from member names gzip /var/spool/mail ... tar: Removing leading `/' from member names Generate import script ... Generate rollback script ... Transfer data to root@newserver:/root/importgroupuser, enter newserver root password: COMMAND RUN: scp -r /root/migrategroupuser root@newserver:/root/importgroupuser root@newserver's password: &lt;&lt;&lt;---<strong>NEWSERVER_ROOT_PASSWORD</strong> d.import-groupuser 100% 1668 1.6KB/s 00:00 d.rollback-groupuser 100% 1291 1.3KB/s 00:00 group.mig 100% 90 0.1KB/s 00:00 gshadow.mig 100% 0 0.0KB/s 00:00 home.tar.gz 100% 61MB 10.2MB/s 00:06 mail.tar.gz 100% 10KB 10.4KB/s 00:00 passwd.mig 100% 1287 1.3KB/s 00:00 shadow.mig 100% 2937 2.9KB/s 00:00 Finished. Next, run /root/migrategroupuser/d.import-groupuser at newserver (*** Use d.rollback-groupuser to undo the job, BUT DO USE WITH CARE ***) </pre><p> ย้ายไปทำที่เครื่อง <code>newserver</code><br /> <code># /root/importgroupuser/d.import-groupuser OK</code></p> <pre> Backup old data and add migrate data to /etc/{passwd,group,shadow,gshadow} ... ~/backupgroupuser ~ Backup /home and /var/spool/mail in /root/backupgroupuser/tar ... tar: Removing leading `/' from member names tar: Removing leading `/' from member names ~ Extract imported data in /root/importgroupuser to /home and /var/spool/mail ... / ~ gunzip /root/importgroupuser/home.tar.gz to / ... gunzip /root/importgroupuser/mail.tar.gz to / ... ~ Import finished. Please delete these files to finish the work: /root/backupgroupuser /root/importgroupuser/d.import-groupuser /root/importgroupuser/d.rollback-groupuser </pre><p> เสร็จแล้ว เครื่องใหม่จะมีชื่อผู้ใช้งานและข้อมูลของผู้ใช้ครบตามเครื่องเก่าทุกประการ<br /> หากสำเร็จเป็นที่พอใจแล้ว ควรลบไฟล์ต่าง ๆ ตามคำแนะนำนะครับ</p> </div></div></div><div class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Topic:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/taxonomy/term/96">bash</a></div></div></div> Thu, 28 Feb 2008 08:44:20 +0000 wd 489 at https://thaitux.info https://thaitux.info/node/489#comments bash tips: ลบไฟล์ไวรัส https://thaitux.info/node/461 <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p>ลูกน้องเอาธัมบ์ไดรฟ์มาให้หาไวรัส<br /> ผลปรากฎว่าพบไฟล์ที่เป็นนามสกุล exe เป็นจำนวนมากภายใต้ไดเรกทอรี่ย่อยเป็นร้อย<br /> ทางแก้คือสแกนแล้วเก็บชื่อไฟล์ไว้ ตัวอย่างของเนื้อไฟล์ที่ถูกสแกนเก็บไว้ เช่น</p> <pre>PhotoShop 7.0/• วิธีทำตัวเยลลลี่ •_files/• วิธีทำตัวเยลลลี่ •_files.exe: W32.Autoit.Obfus FOUND PhotoShop 7.0/• วิธีทำตัวหนังสือชอล์ค •_files/truehitsstat_files/truehitsstat_files.exe: W32.Autoit.Obfus FOUND ...</pre><p> จะเห็นว่ามีรูปแบบที่เราจะตัดโดยใช้คำสั่ง <code>cut</code> ได้คือตั้งแต่เครื่องหมาย <code>:</code> เป็นต้นไป<br /> คำสั่งที่ใช้คือ </p> <pre>cut -d: -f1</pre><p><code>-d:</code> คือใช้ <code>:</code> เป็นตัวแบ่ง<br /> <code>-f1</code> คื่อเมื่อแบ่งแล้ว เราจะเอาสดมถ์ที่ 1 มาใช้งาน</p> <p>แต่เราจะแก้ไขเนื้อไฟล์ให้เหมาะสมเล็กน้อย คือตัดท่อนล่างของไฟล์ออก ให้เหลือเฉพาะชื่อไฟล์ที่ติดไวรัส<br /> แล้วจึงเอาเนื้อไฟล์นั้นมาเป็นข้อมูลเข้า เพื่อจะมาลบไฟล์ที่ติดไวรัสจริง ๆ</p> <p>แต่มีปัญหาเพิ่มคือ ชื่อไฟล์ประกอบด้วยช่องว่างจำนวนมาก ไม่สามารถใช้คำสั่ง <code>for i in `cat file`</code> ได้<br /> ค้นกูเกิลดู พบว่าเขาใช้คำสั่ง <code>while read <em>VARIABLE</em></code></p> <p>สรุปคำสั่งทั้งหมดมาเป็นขั้นตอนดังนี้<br /> สมมุติว่าค้นหาไวรัสในธัมบ์ไดรฟ์ในไดเรกทอรี่ <code>/media/disk</code></p> <p>ไปที่ที่ทำงาน</p> <pre>$ <strong>cd /media/disk</strong></pre><p> สแกนไวรัส แล้วเก็บผลไว้ที่ <code>~/virus.txt</code></p> <pre>$ <strong>clamscan -i -r * &gt; ~/virus.txt</strong></pre><p><code>-i</code> คือให้แสดงเฉพาะไฟล์ที่ติดไวรัส<br /> <code>-r</code> คือให้ขุดลึกลงไปในไดเรกทอรี่ย่อยด้วย</p> <p>แก้ไขไฟล์เล็กน้อย โดยตัดรายงานส่วนท้ายออก<br /> ยกตัวอย่างส่วนที่ตัดออกคือ</p> <pre>$ <strong>vi ~/virus.txt</strong></pre><pre> ----------- SCAN SUMMARY ----------- Known viruses: 203664 Engine version: 0.92 Scanned directories: 97 Scanned files: 1234 Infected files: 252 Data scanned: 378.68 MB Time: 130.603 sec (2 m 10 s)</pre><p> ทีนี้ก็ถึงเวลาลบจริง ๆ แล้ว <strong>***ใช้ด้วยความระมัดระวังนะครับ***</strong><br /> ถ้ายังไม่แน่ใจ อาจแทนที่คำสั่ง <code>rm</code> ด้วยคำสั่ง <code>ls</code> ลองดูก่อน</p> <pre>$ <strong>cat ~/virus.txt | cut -d: -f1 | while read FILE; do rm "$FILE"; done</strong></pre><p> เสร็จแล้วครับ</p> <p><strong>หมายเหตุ</strong></p> <ul> <li>ต้องติดตั้ง clamscan ไว้ก่อน ถ้ายัง ติดตั้งด้วยคำสั่ง<br /> <pre>$ <strong>sudo aptitude install clamav</strong> $ <strong>sudo freshclam</strong></pre></li> <li>ปกติการเมานต์ธัมบ์ไดรฟ์ที่เป็นระบบไฟล์ <code>vfat</code> เขาจะเมานต์ด้วยค่าปริยายด้วยรหัสอักขระภาษาอังกฤษ ทำให้อ่านชื่อไฟล์ภาษาไทยไม่รู้เรื่อง ซึ่งจริง ๆ แล้วต้องตั้งค่ารหัสอักขระเป็น utf-8<br /> เราสามารถบังคับด้วยการเมานต์ใหม่ หรือตั้งค่ารหัสอักขระถาวร ดูวิธีการได้ที่ <a href="http://th.gnome.org/node/6">th.gnome.org: เกร็ดการแก้รหัสอักขระ usb drive</a></li> <li>ถ้ามีไฟล์ชื่อ <code>runauto..</code> เราจะลบไฟล์นี้ตรง ๆ ไม่ได้ ต้องใช้คำสั่งว่า<br /> <code>$ rm runaut~1 -rf</code><br /> ถึงจะลบออก </li></ul> <p><strong>ที่มา</strong></p> <ul> <li><a href="http://www.macgeekery.com/tips/cli/handling_filenames_with_spaces_in_bash">macgeekery: Handling Filenames with Spaces in Bash</a></li> <li><a href="http://sun.newsiczek.pl/2008/02/09/damned-runauto/">Damned runauto..</a></li> </ul> </div></div></div><div class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Topic:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/taxonomy/term/96">bash</a></div></div></div> Mon, 04 Feb 2008 14:49:49 +0000 wd 461 at https://thaitux.info https://thaitux.info/node/461#comments