I was thinking about coding something like this before I found something that was pretty much working already here: Original project
All I did was modify it a bit, changed the default settings for remote browsing, fixed binary file transfers and added a start option.
To use it first install tree, socat:
sudo apt-get install tree
sudo apt-get install socat
Then download the latest copy of bashttpd from here:
https://github.com/AdamDanischewski/bashttpd
Just drop it on a host machine (that has bash) and start it up like this:
$192.168.1.101> bashttpd -s
On the remote machine you should be able to browse and download files from the host server via any web browser by visiting:
http://192.168.1.101:8080
Fun!! =)
Tuesday, April 21, 2015
Thursday, March 26, 2015
Bash CHR program
Bash script that takes ascii code value - character, hexadecimal or octal - and returns corresponding representation:
https://github.com/AdamDanischewski/chr.bsh
Usage: chr.bsh [-D] <-d> <-h|-x> <-b> [-H] <char> [<-a> <code>]
<char> A valid ascii code value: character, decimal,
hexadecimal, octal (0o000 or \000)
OPTIONS:
-d Convert character to decimal
-a Convert code (hex, octal) to ascii character
-h|-x Convert character to hexadecimal
-b Convert character to binary
-o Convert character to octal
-H Show help message
-D Turn on debug mode
-? Show usage
## Options may be duplicated and compounded in any order
$ chr.bsh A -d
65
$ chr.bsh A -d -b
01000001
$ chr.bsh A -d -b -x
0x41
$ chr.bsh A -d -b -x -o
0o101
$ chr.bsh A -d -b -x -o -b
01000001
$ chr.bsh A -d -b -x -o -b -h
0x41
$ chr.bsh A -d -b -x -o -b -h -a
A
## Experimentally - it supports pipes and redirects!
$ echo A | chr.bsh -d -b
01000001
$ chr.bsh -d -b -x <<< A
0x41
## Multiple characters from a string!
$ echo DEF | chr.bsh -d -b
01000100
01000101
01000110
$ chr.bsh -d -b -o <<< XYZ | chr.bsh -a
XYZ
Wednesday, March 25, 2015
Seed /dev/random Instead of Wasting Data on /dev/null
Instead of throwing data that you don't have any other use for into the proverbial bit grinder of /dev/null, why not redirect that data to /dev/random and seed the random data entropy pool?
This excerpt is from the IBM Knowledge Center regarding AIX - but it works similarly on Linux and other Unix variants - if you know better please leave a comment, thanks.
Data written to either of the random devices will also contribute to the pool of stored random input and can influence the output, thus writing to these devices should be a privileged operation. urandom and random Devices
I took a quick backup of my data and then changed all of my scripts in one simple sed:
I did this a few months ago and I felt quite a relief about it, I still recall how relieved I felt at making that change.
This excerpt is from the IBM Knowledge Center regarding AIX - but it works similarly on Linux and other Unix variants - if you know better please leave a comment, thanks.
Data written to either of the random devices will also contribute to the pool of stored random input and can influence the output, thus writing to these devices should be a privileged operation. urandom and random Devices
I took a quick backup of my data and then changed all of my scripts in one simple sed:
sed -i 's@/dev/null@/dev/random@g' *
I did this a few months ago and I felt quite a relief about it, I still recall how relieved I felt at making that change.
Sunday, March 22, 2015
Recursive Awk - Print size in human readable form
num2h.awk
function human(x) {
x[1]/=1024;
if (x[1]>=1000) {
x[2]++; human(x);
}
}
# main
{ a[1]=$1; a[2]=1;
human(a);
print a[1],substr("kMGTEPZY",a[2],1)
}
## alias num2h='awk -f /path/to/num2h.awk <<<'
## >$ num2h 500000
## 488.281 k
## >$ num2h 500000000
## 476.837 M
## >$ num2h 5000000000
## 4.65661 G
Wednesday, March 18, 2015
1980 Porter Stemmer in Awk
################################################################################
# This is the Porter stemming algorithm, coded up in awk by Gregory Grefenstette
# July 5, 2012
# It follows the algorithm presented in
#
# Porter, 1980, An algorithm for suffix stripping, Program, Vol. 14,
# no. 3, pp 130-137,
#
# and more precisely the code for the ANSI C version found at
#
# http://www.tartarus.org/~martin/PorterStemmer
#
# This endioding of the algorthm can be used free of charge for any purpose
#
# TRUE if last two characters are a double consonant
#
# Temporary Modification 20150318 by AMDanischewski
# -- Changed step1ab to also clip -er and -est, this breaks many words
# but it fixes more than it breaks, so I put it on there. Prior to this
# words like lighter and lightest won't be stemmed.
#
# Issues: -er, -est are not stemmed properly
# words ending in -y are brokenly returned as ending -i
#
################################################################################
function doublec(s)
{ if(substr(s,length(s),1) == substr(s,length(s)-1,1) && (substr(s,length(s),1) !~ /[aeiou]/)) return 1;
else return 0 }
# antyhing other than one of a, e, i, o, u, for the case of "y" it checks if
# there is a preceding vowel, in which case it is considered a consonant
function cons(str,i)
{ if(substr(str,i,1) ~ /[aeiou]/) return 0 ;
if(i==1) return 1;
if(substr(str,i,1) == "y") { if(substr(str,i-1,1) ~ /[aeiou]/) return 1; else return 0 }
return 1
}
# cvc(i) is TRUE if last three characters of str are consonant - vowel - consonant
# and also if the second c is not w,x or y. this is used when trying to
# restore an e at the end of a short word. e.g.
#
# cav(e), lov(e), hop(e), crim(e), but
# snow, box, tray.
function cvc(str) {
if(length(str) <= 2) return 0;
if( str ~ /[wxy]$/ ) return 0;
if ( cons(str,length(str)-2) && !cons(str,length(str)-1) && cons(str,length(str)) ) return 1;
return 0
}
# m() measures the number of consonant sequences between k0 and j. if c is
# a consonant sequence and v a vowel sequence, and <..> indicates optional
#
# <c><v> gives 0
# <c>vc<v> gives 1
# <c>vcvc<v> gives 2
# <c>vcvcvc<v> gives 3
# ....
# this version returns "2" as the maximum value
function m(str) {
# skip initial consonants
mreturns=0;
mindex=1;
while((mindex <= length-str) && cons(str,mindex)) mindex++ ;
while (1)
{ while(1)
{ if (mindex > length(str)) return mreturns;
if( cons(str,mindex) ) break;
mindex++
}
mindex++;
mreturns++;
if(mreturns > 2) return mreturns;
while(1)
{ if (mindex > length(str)) return mreturns;
if( ! cons(str,mindex) ) break;
mindex++
}
}
}
# step1ab() gets rid of plurals and -ed or -ing. e.g.
#
# caresses -> caress
# ponies -> poni
# ties -> ti
# caress -> caress
# cats -> cat
#
# feed -> feed
# agreed -> agree
# disabled -> disable
#
# matting -> mat
# mating -> mate
# meeting -> meet
# milling -> mill
# messing -> mess
#
# meetings -> meet
function step1ab(str) {
if(str ~ /sses$/ || str ~ /ies$/ ) str=substr(str,1,length(str)-2) ;
else if(str ~ /ss$/) ;
else if (str ~ /s$/) str=substr(str,1,length(str)-1) ;
if(str ~ /eed$/) { if(m(substr(str,1,length(str)-3))>0 ) str=substr(str,1,length(str)-1) ; }
else {trunc=0;
if (str ~ /[aeiouy].*ed$/) trunc=2;
## Begin temporary modification by AMDanischewski - 20150318
## Added the following two entries to fix est and er.
## Without this words like lightest and lighter won't be stemmed.
## So this needs to be tweaked furth =) ..
if (str ~ /[aeiouy].*er$/) trunc=2;
if (str ~ /[aeiouy].*est$/) trunc=3;
if (str ~ /[aeiouy].*ing$/) trunc=3 ;
if(trunc>0) { str=substr(str,1,length(str)-trunc) ;
if(str ~ /(at|bl|iz)$/) str=str"e" ;
else
if (doublec(str)==1 && (str !~ /[lsz]$/)) { str=substr(str,1,length(str)-1); }
else if( m(str)==1 && cvc(str)) str=str"e";
}}
return str }
# step1c() turns terminal y to i when there is another vowel in the stem.
function step1c(str) {
if(str ~/[aeiouy].*y$/) str=substr(str,1,length(str)-1)"i" ;
return str }
# step2() maps double suffices to single ones. so -ization ( = -ize plus
# -ation) maps to -ize etc. note that the string before the suffix must give
# m() > 0. */
function step2(str) {
if( str ~ /[aeiouy][^aeiouy].*ational$/ ) str=substr(str,1,length(str)-5)"e" ;
else if ( str ~ /[aeiouy][^aeiou].*tional$/ ) str=substr(str,1,length(str)-2) ;
else if ( str ~ /[aeiouy][^aeiou].*[ae]nci$/ ) str=substr(str,1,length(str)-1)"e" ;
else if ( str ~ /[aeiouy][^aeiou].*izer$/ ) str=substr(str,1,length(str)-1) ;
else if ( str ~ /[aeiouy][^aeiou].*bli$/ ) str=substr(str,1,length(str)-1)"e" ;
else if ( str ~ /[aeiouy][^aeiou].*alli$/ ) str=substr(str,1,length(str)-2);
else if ( str ~ /[aeiouy][^aeiou].*entli$/ ) str=substr(str,1,length(str)-2);
else if ( str ~ /[aeiouy][^aeiou].*eli$/ ) str=substr(str,1,length(str)-2);
else if ( str ~ /[aeiouy][^aeiou].*ousli$/ ) str=substr(str,1,length(str)-2);
else if ( str ~ /[aeiouy][^aeiou].*ization$/ ) str=substr(str,1,length(str)-5)"e" ;
else if ( str ~ /[aeiouy][^aeiou].*ation$/ ) str=substr(str,1,length(str)-3)"e" ;
else if ( str ~ /[aeiouy][^aeiou].*ator$/ ) str=substr(str,1,length(str)-2)"e" ;
else if ( str ~ /[aeiouy][^aeiou].*alism$/ ) str=substr(str,1,length(str)-3);
else if ( str ~ /[aeiouy][^aeiou].*iveness$/ ) str=substr(str,1,length(str)-4) ;
else if ( str ~ /[aeiouy][^aeiou].*fulness$/ ) str=substr(str,1,length(str)-4) ;
else if ( str ~ /[aeiouy][^aeiou].*ousness$/ ) str=substr(str,1,length(str)-4) ;
else if ( str ~ /[aeiouy][^aeiou].*aliti$/ ) str=substr(str,1,length(str)-3) ;
else if ( str ~ /[aeiouy][^aeiou].*iviti$/ ) str=substr(str,1,length(str)-3)"e" ;
else if ( str ~ /[aeiouy][^aeiou].*biliti$/ ) str=substr(str,1,length(str)-5)"le" ;
else if ( str ~ /[aeiouy][^aeiou].*logi$/ ) str=substr(str,1,length(str)-1) ;
return str }
# step3() deals with -ic-, -full, -ness etc. similar strategy to step2.
function step3(str) {
if( str ~ /[aeiouy][^aeiouy].*icate$/ ) str=substr(str,1,length(str)-3) ;
else if ( str ~ /[aeiouy][^aeiou].*ative$/ ) str=substr(str,1,length(str)-5);
else if ( str ~ /[aeiouy][^aeiou].*alize$/ ) str=substr(str,1,length(str)-3) ;
else if ( str ~ /[aeiouy][^aeiou].*iciti$/ ) str=substr(str,1,length(str)-3) ;
else if ( str ~ /[aeiouy][^aeiou].*ical$/ ) str=substr(str,1,length(str)-2) ;
else if ( str ~ /[aeiouy][^aeiou].*ful$/ ) str=substr(str,1,length(str)-3);
else if ( str ~ /[aeiouy][^aeiou].*ness$/ ) str=substr(str,1,length(str)-4);
return str }
# step4() takes off -ant, -ence etc., in context <c>vcvc<v>.
function step4(str) {
if( str ~ /al$/ ) { if ( m(substr(str,1,length(str)-2)) > 1 ) str=substr(str,1,length(str)-2) }
else if ( str ~ /[ae]nce$/ ) { if ( m(substr(str,1,length(str)-4)) > 1) str=substr(str,1,length(str)-4) }
else if ( str ~ /(er|ic)$/ ) { if ( m(substr(str,1,length(str)-2)) > 1 ) str=substr(str,1,length(str)-2) }
else if ( str ~ /[ai]ble$/ ) { if ( m(substr(str,1,length(str)-4)) > 1 ) str=substr(str,1,length(str)-4) }
else if ( str ~ /ant$/ ) { if ( m(substr(str,1,length(str)-3)) > 1 ) str=substr(str,1,length(str)-3) }
else if ( str ~ /ement$/) { if( m(substr(str,1,length(str)-5)) > 1 ) str=substr(str,1,length(str)-5) }
else if ( str ~ /ment$/) { if ( m(substr(str,1,length(str)-4)) > 1 ) str=substr(str,1,length(str)-4) }
else if ( str ~ /ent$/) { if ( m(substr(str,1,length(str)-3)) > 1 ) str=substr(str,1,length(str)-3) }
else if ( str ~ /[st]ion$/) { if ( m(substr(str,1,length(str)-3)) > 1 ) str=substr(str,1,length(str)-3) }
else if ( str ~ /ou$/) { if ( m(substr(str,1,length(str)-2)) > 1 ) str=substr(str,1,length(str)-2) }
else if ( str ~ /(ism|ate|iti|ous|ive|ize)$/) { if ( m(substr(str,1,length(str)-3)) > 1 ) str=substr(str,1,length(str)-3)
}
return str}
# step5() removes a final -e if m() > 1, and changes -ll to -l if
# m() > 1.
function step5(str) {
if ( str ~ /e$/ && ( m(str)>1 || (m(str)==1 && !cvc(substr(str,1,length(str)-1))))) str=substr(str,1,length(str)-1) ;
if( str ~ /ll$/ && m(str)>1 ) str=substr(str,1,length(str)-1) ;
return str }
function stem(str)
{ str=tolower(str);
if(length(str)<=2) return str;
str=step1ab(str);
str=step1c(str);
str=step2(str);
str=step3(str);
str=step4(str);
str=step5(str);
return str
}
# main
{ printf("%s",stem($1));
for(i=2;i<=NF;i++) printf("%s%s",FS,stem($i));
print ""
}
alias stem='awk -f /path/to/stem.awk <<< '
Now you should be able to stem any word like this:
~$ stem shopping
shopMonday, March 16, 2015
Who needs "Toilet", A Simple Bash Colorizer
#!/usr/bin/env bash
## A.M.Danischewski 2015+(c) Free - for (all (uses and
## modifications)) - except you must keep this notice intact.
declare INPUT_TXT=""
declare ADD_LF="\n"
declare -i DONE=0
declare -r COLOR_NUMBER="${1:-247}"
declare -r ASCII_FG="\\033[38;05;"
declare -r COLOR_OUT="${ASCII_FG}${COLOR_NUMBER}m"
function show_colors() {
## perhaps will add bg 48 to first loop eventually
for fgbg in 38; do for color in {0..256} ; do
echo -en "\\033[${fgbg};5;${color}m ${color}\t\\033[0m";
(($((${color}+1))%10==0)) && echo; done; echo; done
}
if [[ ! $# -eq 1 || ${1} =~ ^-. ]]; then
show_colors
echo " Usage: ${0##*/} <color fg>"
echo " E.g. echo \"Hello world!\" | figlet | ${0##*/} 54"
else
while IFS= read -r PIPED_INPUT || { DONE=1; ADD_LF=""; }; do
PIPED_INPUT=$(sed 's#\\#\\\\#g' <<< "${PIPED_INPUT}")
INPUT_TXT="${INPUT_TXT}${PIPED_INPUT}${ADD_LF}"
((${DONE})) && break;
done
echo -en "${COLOR_OUT}${INPUT_TXT}\\033[00m"
fi
Friday, March 13, 2015
Geany custom command - Parenthesize selected text
Here is quick little bash script that accepts piped input from STDIN and parenthesizes it.
I use it for a Geany Custom Command, to set it up from the Geany IDE:
Choose: -> Edit -> Format -> Send Selection To -> Set Custom Commands -> Add
Then put the full path of this script for the Command and provide a Label: Parenthesize.
If it is the first command it will automatically have the keybinding of Control+1, so now
whenever you select any block of text you can simply hit Control+1 and the selected text will be automatically parenthesized for you.
I use it for a Geany Custom Command, to set it up from the Geany IDE:
Choose: -> Edit -> Format -> Send Selection To -> Set Custom Commands -> Add
Then put the full path of this script for the Command and provide a Label: Parenthesize.
If it is the first command it will automatically have the keybinding of Control+1, so now
whenever you select any block of text you can simply hit Control+1 and the selected text will be automatically parenthesized for you.
#!/usr/bin/env bash
declare INPUT_TXT=""
declare ADD_LF="\n"
declare -i DONE=0
while read PIPED_INPUT || { DONE=1; ADD_LF=""; }; do
INPUT_TXT="${INPUT_TXT}${PIPED_INPUT}${ADD_LF}"
((${DONE})) && break;
done
echo -en "(${INPUT_TXT})"
Sunday, March 8, 2015
Bash Random ID Generator - Based on mouse input, time, /dev/urandom, dynamic/static text
Description: gen_uniq_id.bsh This program generates a random md5sum based on the current time to nanoseconds
and collected mouse movement data/random data over .25 seconds or to an
user-specified floating point timeframe. This program requires (to work to full capacity) by default: md5sum, timeout, xinput, /dev/urandom This program is self-modifying and intentionally sensitive to line number changes. This program generates a random number based on the current time to the nanosecond (date +%Y%m%d%H%M%S%N), combined with by default .25 seconds of mouse data combined with .25 seconds of random data. This script currently outputs a random md5sum of a string consisting of the current time, a block of text, mouse movement data and random data. The default mouse device id currently set is 11, the default this script "ships" with is 11 this is likely wrong for your system so you will need to change it to the appropriate value. You may set a new default value using the -M option. The appropriate mouse device id to use can be determined by running: xinput --list The default random device id currently set is /dev/urandom, the default the script "ships" with is /dev/urandom which usually exists on most `*`nix boxes. If you would like to use a random device other than the current default you may set a new default value using the -R option. The default text currently set is: "I AM A SOVEREIGN EVERLASTING SENTIENT FROM THE NUMBER LINE WITHOUT A CREATOR" You can also supply your own text statement dynamically with the -s option, this allows for further random seeding opportunity. If you like to use a different statement text you may set a new default value using the -S option. WARNING: -M, -R, -S options require that ${0} (now set to ./gen_uniq_id.bsh) refer to the script, either a fully qualified path /favorite/place/for/${0} or ${0} to refer to the script you wish to modify that is in your current directory. These options require further that you have write permission on ${0}. The -M, -R, -S options should only need to be issued VERY INFREQUENTLY, once they are run the values become the new DEFAULT values. If you have modified this script at all, or you think for any reason the line numbers have changed then these options will likely fail. It is recommended that you make a copy to a sandbox directory and test it there before running it on your main copy of this script. The script does make a backup of the original script but the backup will get clobbered from repeated use. If these options are too scary, then I recommend you modify this script and comment out the logic in the case statement of the option handler. From there you can modify this script manually when necessary. Usage: gen_uniq_id.bsh <-h> <-d> <-m=[0.00..]> <-r=[0.00..]> <-s="YOUR QUOTE"> OPTIONS: -h Show this message -d Turn on debug mode -m=0.00.. Mouse data collection time, 0 turns off mouse data, any float turns on collecting mouse movement data for the random generated. Default is (.25 seconds) -r=0.00.. Random data collection time, 0 turns off random data collection, any float turns on collecting random data for the duration time in seconds for the random generated. Default is (.25 seconds) -s String of text to incorporate into the random md5sum -M=0-20.. Change default value of mouse device id (that corresponds to xinput --list mouse device id) -R="/dev/.." Change default value of the random device to use -S="U QUOTE" Change default value of the STATEMENT STRING E.g. ## To generate a random md5sum based on random data collected ## over .5 seconds and 1 second of collected mouse movement data $ gen_uniq_id.bsh -r.5 -m1 ## To generate a random md5sum based on random data collected ## over 0.004353 seconds without any collected mouse movement data $ gen_uniq_id.bsh -r".000004353354e+03" -m0 ## To turn off mouse collection, and random collection and ## seed with the last 5 commands from history w/debug on to see $ gen_uniq_id.bsh -d -m0 -r0 -s$(history|tail -5) ## To generate a random md5sum without random data collected ## and without any collected mouse movement data and with a ## custom default text $ gen_uniq_id.bsh -r0 -m0 -s="For my benefit only, I .." ## To debug and see all internal variables $ gen_uniq_id.bsh -d 2>&1 | more ## To change the defaults for the mouse dev to device id 10, ## random device to /dev/really_quick_random and ## statement to "A DECLARATION OF SOVEREIGNTY NEED NO WITNESS" $ gen_uniq_id.bsh -M=10 -R="/dev/really_quick_random" \ -S="A DECLARATION OF SOVEREIGNTY NEED NO WITNESS"
Wednesday, February 18, 2015
USB MicroSd Card Storage Solution using ZFS on Linux - Fast, Reliable & Inexpensive!
Recently a nearly brand new WD MyBook 4TB died unexpectedly, so I have been reorganizing for the future.
Enter ZFS as my first choice in filesystems to move forward with and the results are very promising so far. In particular I have had very decent results with the deduplication feature and compression.
Interestingly though these features are so new they lack of current support in many common system utilities like df so using them will get you inaccurate results. For instance df cannot handle deduplication, once you start putting extra GB's of dedup'd files on it starts lying about it and tells you the disk is much bigger than it really is. Also because a lot of stuff is going on in memory you never really know exactly how fast things are going, so the throughput is probably a bit lied about too. So the end result is basically you don't really know how much space you have at any given time or how fast it is, yet you get the general sense that its safe, at least I did. I was able to break and repair the zpool several times, simulate corruption and scrub it back and resilver new disks.
Also to be as accurate as possible with these numbers, to make sure the files weren't simply sitting in memory cached and not written I kept checking zpool iostat -v (I saw what looked like write operations queued up and slowly dwindling down). Strangely du -sh said the full file was there, I md5sum'd it and it had the same signature as the original file and finally to settle it with certainty I shutdown zfs-fuse itself (which quickly unmounted the filesystems) and disconnected / reconnected the drives and then brought zfs-fuse back up and sure enough the full file was there. Seems a bit like Voodoo, but it works well enough for me.
I realize these numbers I achieved are probably not 100% accurate because of all the memory caching and compression but it doesn't really matter for my needs. What I need is to be able to survive a drive loss and continue to function until the new drive is brought online while not being sluggish. ZFS accomplishes all that and more - like deduplication, compression, scrubbing (against bitrot) and snapshots. Plus its free so I am very content with ZFS. Here is my setup and results:
Acer C720 (w/2GB RAM) - Chromeos Crouton/chroot'd to Ubuntu 14.04 (Trusty)
Upgraded SSD to a 128 GB MyDigital SSD w/6GB SuperCache2
1 Vantec 10 port USB 3.0 hub ($45 from NewEgg)
(Update Feb 19, 2015 looks like the price is now $60 for this)
5 USB 3.0 MicroSD SDXC Card Readers (5 x $5 AliExpress)
5 SanDisk MicroSD 128GB (5 x $13 AliExpress)
Grand Total $135
ZFS-FUSE (apt-get install zfs-fuse)
cp normal file speed averages approximately 300MB/s !!
The normal speed for these drives (formatted exFat or Fat32) is approximately 29MB/s, so even with striping redundancy the speed is approximately 1000% increased. Not bad! =)
time cp big_file_00.big_file /MYWINPOOL/
‘big_file_00.big_file’ -> ‘/MYWINPOOL/big_file_00.big_file’
real 0m1.030s
user 0m0.007s
sys 0m0.360s
(trusty)cronkilla@localhost:/MYWINPOOL$ du -sh big_file_00.big_file
300M big_file_00.big_file
(Note: big_file was created via dd if=/dev/urandom)
Sequential benchmark performance using /dev/zero (my alias bm): ranges from 490MB/s to 540MB/s
To obtain these results I upped the max-arc-size from the the ZFS configuration file (/etc/zfs/zfsrc) from 100 to 1000,
this had a big impact. I also changed a few other parameters:
max-arc-size = 1000
fuse-mount-options = default_permissions,big_writes,allow_other
#zfs-prefetch-disable ### This was uncommented and I commented it out
(trusty)cronkilla@localhost:~$ sudo zpool history MYWINPOOL
History for 'MYWINPOOL':
2015-02-18.18:51:15 zpool create -f MYWINPOOL raidz1 /dev/disk/by-id/usb-Generic_STORAGE_DEVICE_FUNWAY091552-0:0 /dev/disk/by-id/usb-Generic_STORAGE_DEVICE_FUNWAY091125-0:0 /dev/disk/by-id/usb-Generic_STORAGE_DEVICE_FUNWAY091147-0:0 /dev/disk/by-id/usb-Generic_STORAGE_DEVICE_FUNWAY091067-0:0 /dev/disk/by-id/usb-Generic_STORAGE_DEVICE_FUNWAY090855-0:0
2015-02-18.18:53:26 zfs set compression=zle MYWINPOOL
2015-02-18.18:53:27 zfs set checksum=fletcher4 MYWINPOOL
2015-02-18.18:53:29 zfs set dedup=on MYWINPOOL
2015-02-18.18:53:30 zfs set xattr=off MYWINPOOL
2015-02-18.18:53:31 zfs set atime=off MYWINPOOL
Here is a quick glimpse at what it looked like during a write test via zpool iostat -v:
(trusty)cronkilla@localhost:~$ sudo zpool iostat -v
capacity operations bandwidth
pool alloc free read write read write
-------------------------------------- ----- ----- ----- ----- ----- -----
MYWINPOOL 151M 596G 0 27 834 1.89M
raidz1 151M 596G 0 27 834 1.89M
disk/by-id/usb-Generic_STORAGE_DEVICE_FUNWAY091552-0:0 - - 0 9 13.7K 493K
disk/by-id/usb-Generic_STORAGE_DEVICE_FUNWAY091125-0:0 - - 0 9 13.7K 495K
disk/by-id/usb-Generic_STORAGE_DEVICE_FUNWAY091147-0:0 - - 0 10 13.7K 501K
disk/by-id/usb-Generic_STORAGE_DEVICE_FUNWAY091067-0:0 - - 0 9 14.6K 500K
disk/by-id/usb-Generic_STORAGE_DEVICE_FUNWAY090855-0:0 - - 0 11 13.7K 509K
-------------------------------------- ----- ----- ----- ----- ----- -----
Here is more detailed disk data, showing through the first disk not the remaining disks:
(trusty)cronkilla@localhost:~$ sudo zdb
MYWINPOOL:
version: 23
name: 'MYWINPOOL'
state: 0
txg: 4
pool_guid: 17797988667815477235
hostid: 8323328
hostname: 'localhost'
vdev_children: 1
vdev_tree:
type: 'root'
id: 0
guid: 17797988667815477235
create_txg: 4
children[0]:
type: 'raidz'
id: 0
guid: 16975055505754696246
nparity: 1
metaslab_array: 23
metaslab_shift: 32
ashift: 9
asize: 644221501440
is_log: 0
create_txg: 4
children[0]: id: 0
guid: 13728714778704373774
path: '/dev/disk/by-id/usb-Generic_STORAGE_DEVICE_FUNWAY091552-0:0'
whole_disk: 0
create_txg: 4
...
In conclusion, I found ZFS with MicroSD cards to be particularly a decent pairing since MicroSD cards are super cheap and ZFS is already a software RAID Controller. ZFS provides resiliency against bitrot via scrubbing, RAID redundancy against drive failures and snapshots so ZFS w/MicroSD cards - in my opinion - makes for a nearly perfect complementary match.
As of Feb 19, 2015 - this won't work directly for Windows since Windows doesn't support ZFS - but there is VirtualBox / drag-and-drop Guest Additions pass-throughs.. =)
Enter ZFS as my first choice in filesystems to move forward with and the results are very promising so far. In particular I have had very decent results with the deduplication feature and compression.
Interestingly though these features are so new they lack of current support in many common system utilities like df so using them will get you inaccurate results. For instance df cannot handle deduplication, once you start putting extra GB's of dedup'd files on it starts lying about it and tells you the disk is much bigger than it really is. Also because a lot of stuff is going on in memory you never really know exactly how fast things are going, so the throughput is probably a bit lied about too. So the end result is basically you don't really know how much space you have at any given time or how fast it is, yet you get the general sense that its safe, at least I did. I was able to break and repair the zpool several times, simulate corruption and scrub it back and resilver new disks.
Also to be as accurate as possible with these numbers, to make sure the files weren't simply sitting in memory cached and not written I kept checking zpool iostat -v (I saw what looked like write operations queued up and slowly dwindling down). Strangely du -sh said the full file was there, I md5sum'd it and it had the same signature as the original file and finally to settle it with certainty I shutdown zfs-fuse itself (which quickly unmounted the filesystems) and disconnected / reconnected the drives and then brought zfs-fuse back up and sure enough the full file was there. Seems a bit like Voodoo, but it works well enough for me.
I realize these numbers I achieved are probably not 100% accurate because of all the memory caching and compression but it doesn't really matter for my needs. What I need is to be able to survive a drive loss and continue to function until the new drive is brought online while not being sluggish. ZFS accomplishes all that and more - like deduplication, compression, scrubbing (against bitrot) and snapshots. Plus its free so I am very content with ZFS. Here is my setup and results:
Acer C720 (w/2GB RAM) - Chromeos Crouton/chroot'd to Ubuntu 14.04 (Trusty)
Upgraded SSD to a 128 GB MyDigital SSD w/6GB SuperCache2
1 Vantec 10 port USB 3.0 hub ($45 from NewEgg)
(Update Feb 19, 2015 looks like the price is now $60 for this)
5 USB 3.0 MicroSD SDXC Card Readers (5 x $5 AliExpress)
5 SanDisk MicroSD 128GB (5 x $13 AliExpress)
Grand Total $135
ZFS-FUSE (apt-get install zfs-fuse)
cp normal file speed averages approximately 300MB/s !!
The normal speed for these drives (formatted exFat or Fat32) is approximately 29MB/s, so even with striping redundancy the speed is approximately 1000% increased. Not bad! =)
time cp big_file_00.big_file /MYWINPOOL/
‘big_file_00.big_file’ -> ‘/MYWINPOOL/big_file_00.big_file’
real 0m1.030s
user 0m0.007s
sys 0m0.360s
(trusty)cronkilla@localhost:/MYWINPOOL$ du -sh big_file_00.big_file
300M big_file_00.big_file
(Note: big_file was created via dd if=/dev/urandom)
Sequential benchmark performance using /dev/zero (my alias bm): ranges from 490MB/s to 540MB/s
To obtain these results I upped the max-arc-size from the the ZFS configuration file (/etc/zfs/zfsrc) from 100 to 1000,
this had a big impact. I also changed a few other parameters:
max-arc-size = 1000
fuse-mount-options = default_permissions,big_writes,allow_other
#zfs-prefetch-disable ### This was uncommented and I commented it out
(trusty)cronkilla@localhost:~$ sudo zpool history MYWINPOOL
History for 'MYWINPOOL':
2015-02-18.18:51:15 zpool create -f MYWINPOOL raidz1 /dev/disk/by-id/usb-Generic_STORAGE_DEVICE_FUNWAY091552-0:0 /dev/disk/by-id/usb-Generic_STORAGE_DEVICE_FUNWAY091125-0:0 /dev/disk/by-id/usb-Generic_STORAGE_DEVICE_FUNWAY091147-0:0 /dev/disk/by-id/usb-Generic_STORAGE_DEVICE_FUNWAY091067-0:0 /dev/disk/by-id/usb-Generic_STORAGE_DEVICE_FUNWAY090855-0:0
2015-02-18.18:53:26 zfs set compression=zle MYWINPOOL
2015-02-18.18:53:27 zfs set checksum=fletcher4 MYWINPOOL
2015-02-18.18:53:29 zfs set dedup=on MYWINPOOL
2015-02-18.18:53:30 zfs set xattr=off MYWINPOOL
2015-02-18.18:53:31 zfs set atime=off MYWINPOOL
Here is a quick glimpse at what it looked like during a write test via zpool iostat -v:
(trusty)cronkilla@localhost:~$ sudo zpool iostat -v
capacity operations bandwidth
pool alloc free read write read write
-------------------------------------- ----- ----- ----- ----- ----- -----
MYWINPOOL 151M 596G 0 27 834 1.89M
raidz1 151M 596G 0 27 834 1.89M
disk/by-id/usb-Generic_STORAGE_DEVICE_FUNWAY091552-0:0 - - 0 9 13.7K 493K
disk/by-id/usb-Generic_STORAGE_DEVICE_FUNWAY091125-0:0 - - 0 9 13.7K 495K
disk/by-id/usb-Generic_STORAGE_DEVICE_FUNWAY091147-0:0 - - 0 10 13.7K 501K
disk/by-id/usb-Generic_STORAGE_DEVICE_FUNWAY091067-0:0 - - 0 9 14.6K 500K
disk/by-id/usb-Generic_STORAGE_DEVICE_FUNWAY090855-0:0 - - 0 11 13.7K 509K
-------------------------------------- ----- ----- ----- ----- ----- -----
Here is more detailed disk data, showing through the first disk not the remaining disks:
(trusty)cronkilla@localhost:~$ sudo zdb
MYWINPOOL:
version: 23
name: 'MYWINPOOL'
state: 0
txg: 4
pool_guid: 17797988667815477235
hostid: 8323328
hostname: 'localhost'
vdev_children: 1
vdev_tree:
type: 'root'
id: 0
guid: 17797988667815477235
create_txg: 4
children[0]:
type: 'raidz'
id: 0
guid: 16975055505754696246
nparity: 1
metaslab_array: 23
metaslab_shift: 32
ashift: 9
asize: 644221501440
is_log: 0
create_txg: 4
children[0]: id: 0
guid: 13728714778704373774
path: '/dev/disk/by-id/usb-Generic_STORAGE_DEVICE_FUNWAY091552-0:0'
whole_disk: 0
create_txg: 4
...
In conclusion, I found ZFS with MicroSD cards to be particularly a decent pairing since MicroSD cards are super cheap and ZFS is already a software RAID Controller. ZFS provides resiliency against bitrot via scrubbing, RAID redundancy against drive failures and snapshots so ZFS w/MicroSD cards - in my opinion - makes for a nearly perfect complementary match.
As of Feb 19, 2015 - this won't work directly for Windows since Windows doesn't support ZFS - but there is VirtualBox / drag-and-drop Guest Additions pass-throughs.. =)
Tuesday, January 27, 2015
Basic Windows Security
First if you have a serious problem you would be best to repair utilizing another OS, either a bootable USB (E.g. Linux/Knoppix) or another machine entirely.
I recommend following some online hardening guides, however you may cause headaches if you shutdown too many services, I recommend you take many well-named restore points along the way and test the functionality of whatever programs you plan to use.
This is a useful guide: Hardening Windows 8.1
Note: ** Do Not ** download the recommended software in the guide: Software Restriction Policy 1.2 - Although it is hosted on Sourceforge multiple scanners have detected a Trojan (Artemesis). Generally you should be extremely careful about downloading any software from popular file-sharing sites including yet not limited to CNET, Sourceforge, etc. If you have an option to download from the author / developer / owner website directly - I recommend that you always choose that option. Furthermore if you see MD5 or SHA1 hash sums always check to make sure they match *before* you install the program. And scan everything! A good line of defense will have multiple tiers: E.g. Antivirus (E.g. McAfee) -> Spyware (E.g. Malwarebytes Anti-Malware, SpyHunter, Spybot Search & Destroy) then even another level can be herdProtect Anti-Malware. If you have to utilize CNET to obtain software you should use everything you have to check it out before using it and it is recommended to sandbox/jail it or run it from within a VM to see what it does before using it on your real system.
After getting all the antivirus, malware and adware removed you can cautiously begin to connect your system back to the internet.
Download and install EMET directly from Microsoft (latest version as of this post Apr, 04 2015 is EMET 5.2) - preferably from another machine while staying still offline: Microsoft - Enhanced Mitigation Experience Toolkit 5.2
Microsoft EMET is free and is key to making your Windows box secure, when turned up to the maximum protection level EMET thwarts a huge variety of threats and is defeatable only by the latest-and-greatest threats out there.
After EMET is installed and the settings are configured to ALWAYS ON, one of the first things to run are some of the free Microsoft built-in repair tools.
First up is to run System File Checker, run the following from an elevated command prompt - read more at Microsoft Support - Use SFC to repair missing or corrupted system files:
C:\> sfc /scannow
Next run the Deployment Imaging and Servicing Management (DISM) tool to repair any Windows Image corruption, the /online flag tells DISM to use Windows Update for the repair image source - you can read more about it at Microsoft Technet- Repair a Windows Image:
C:\> dism /online /cleanup-image /restorehealth
Further ways to be secure, as the guide I linked to above recommends there is a software called Sandboxie that is really remarkable and it is free for one sandbox. Yet it is so useful that it is one of the few programs that I use that I decided to buy for extended features.
Sandboxie allows for jailing applications, so you can install and run applications from the sandbox without the application being capable of tampering with your real system files. When you install a program you can see exactly what it does, what registry entries it would have made where it would put files. Also when it runs you can see all the files that its accessing. If you don't like something with a single click you can wipe out everything that it did without affecting your real system.
Sandboxie is also EMET aware and is actively being developed (as of Jan 27,2015).
I have sandboxed on my system Firefox, Cygwin to name a few useful ones - I recommend to keep Firefox sandboxed at all times and additionally to install the add-on No Script and put it on the maximum protection settings whitelisting and opening up whatever features you need along the way and also a decent anti-keylogger (as of Feb 2, 2015 - QFX Key Scrambler works well and is free).
Furthermore I recommend you image your system (E.g.using Clonezilla, Macrium Reflect) and consider utilizing Virtual Machines (E.g. VirtualBox, VMware are both free) for anything really risky before you try it on your real system.
Lastly if you really want to take it to the next level you can familiarize yourself with the way Military/DoD and Government Agencies secure their Windows computers, here: IASE
Windows 8 STIG - Version 1, Release 8 (Last Updated: Jan 23,2015)
Windows Operating Systems Overview (Last Updated: Jan 23,2015)
Monday, January 26, 2015
Alias lscmd - colorized grep for cmd data (w/ ps & lsof)
alias lscmd='_(){ CP="\\033[1;3" && Y="${CP}3m" && R="${CP}1m" && P="${CP}5m" && B="${CP}4m" && C="${CP}6m" && G="${CP}2m" && RST="${CP}0m" && if [[ $# -eq 0 ]] || [[ ${1} =~ ^- ]]; then echo -en "${Y}Usage: lscmd <cmd to grep for>${RST}\n"; else CHR1="${1:0:1}"; PSOUT=$(ps -ef | grep "[${CHR1}]${1:1}" 2>/dev/null); local -i PIDCHOICE=1; MATCHCOUNT=$(echo "${PSOUT}"|wc -l);if [[ "${MATCHCOUNT}" -gt 1 ]]; then PSOUT=$(echo "${PSOUT}" | cat -n); echo "${PSOUT}" | awk "{printf \"${Y}%s ${RST}\",\$1;\$1=\"\";printf \"${G}%s${RST}\n\",\$0}"; read -p "$(echo -en "${Y}Multiple matches found, enter number of process: ${RST}${G}")" -u 0 PIDCHOICE; echo -en "${RST}"; fi; if [[ -z "${PSOUT}" ]]; then echo -e "${Y}lscmd:: ${RST}${R}No Matches Found ${RST}${Y}(${RST}${G}grep${RST}${Y}\x27ing${RST} ${G}ps${RST}${Y}) for:${RST} ${B}${1}${RST}"; else TARGETPID=$(echo "${PSOUT}"|sed -n "${PIDCHOICE}p" | awk "{print \$2}"); CMDHEAD=$(/bin/ps --no-headers -p "${TARGETPID}" -o comm,pid -ww | awk "{printf \"${B}Command shortname: ${RST}${C}%s ${RST} ${B}Pid: ${RST}${C}%s${RST}\",\$1,\$2}");CMDLONG=$(/bin/ps --no-headers -p "${TARGETPID}" -o cmd -ww); CMDFILES=$(lsof -p "${TARGETPID}" 2>/dev/null | sed "1s#.*#\\${B}&\\${RST}#;1!s#^.*\$#\\${G}&\\${RST}#g"); OUTPUT1="${CMDHEAD}";OUTPUT2="${B}Full Command: ${RST}${Y}${CMDLONG}${RST}"; OUTPUT3="${CMDFILES}";echo -en "${OUTPUT1}\n${OUTPUT2}\n${OUTPUT3}${RST}\n"|more; fi; fi; }; _'
This command will grep ps for the term provided. If multiple matches are found the user will be presented with a number selection of matching commmands and a prompt to enter the choice (not the pid) of the process they wish to see data on.
/tmp/test$ Usage: lscmd <cmd to grep for>
/tmp/test$ lscmd yate
1 1000 9999 30794 6 Jan25 pts/1 01:02:07 yate
2 1000 28125 15877 1 01:11 pts/3 00:17:47 clients/yate-qt4 -c ./conf.d -m ./modules -e ./share
Multiple matches found, enter number of process: 1
Command shortname: yate Pid: 9999
Full Command: yate
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
yate 9999 cronkilla rtd DIR 8,1 4096 391664 /
yate 9999 cronkilla txt REG 8,1 6088 485695 /usr/bin/yate
yate 9999 cronkilla mem REG 8,1 39576 634867 /usr/lib/yate/jingle/jinglef
eatures.yate yate 9999 cronkilla mem REG 8,1 105952 634890 /usr/lib/yate/server/ysigcha n.yate
yate 9999 cronkilla mem REG 8,1 31144 634881 /usr/lib/yate/server/mrcpspe ech.yate
yate 9999 cronkilla mem REG 8,1 18696 634876 /usr/lib/yate/server/dbwave. yate
yate 9999 cronkilla mem REG 8,1 31088 634875 /usr/lib/yate/server/dbpbx.y ate
yate 9999 cronkilla mem REG 8,1 18856 634869 /usr/lib/yate/server/accfile .yate
yate 9999 cronkilla mem REG 8,1 54960 634889 /usr/lib/yate/server/yradius .yate
yate 9999 cronkilla mem REG 8,1 22832 634882 /usr/lib/yate/server/park.ya
Subscribe to:
Posts (Atom)

