Showing posts with label Tips/Tricks. Show all posts
Showing posts with label Tips/Tricks. Show all posts

Wednesday, September 19, 2012

Detect increased new size of existing LUN in RHEL by rescanning FC port without reboot

If the usual command :

echo “- - -“ > /sys/class/scsi_host/hostX/scan

doesn’t work for FC target, you can try this:

echo 1 > /sys/devices/{PCI-DEVICE-ID} /rescan 

The path is the device path to the FC target,which may have multiple paths. The scsi-rescan(rescan-scsi-bus.sh) tool in sg3_utils worked great for new LUN but it couldn’t detect the new size of existing LUN neither. The following procedure was tested in RHEL 6.3.



#Find the PCI ID of your device
>lspci | grep -i qlogic
15:00.0 Fibre Channel: QLogic Corp. ISP2532-based 8Gb Fibre Channel to PCI Express HBA (rev 02)
1a:00.0 Fibre Channel: QLogic Corp. ISP2532-based 8Gb Fibre Channel to PCI Express HBA (rev 02)
#Find the file rescan in /sys/devices by filtering PCI ids found above
>find /sys/devices  -name rescan  | egrep '15:00|1a:00'
/sys/devices/pci0000:00/0000:00:03.0/0000:15:00.0/rescan
/sys/devices/pci0000:00/0000:00:03.0/0000:15:00.0/host1/rport-1:0-0/target1:0:0/1:0:0:0/rescan
/sys/devices/pci0000:00/0000:00:03.0/0000:15:00.0/host1/rport-1:0-1/target1:0:1/1:0:1:0/rescan
/sys/devices/pci0000:00/0000:00:07.0/0000:1a:00.0/rescan
/sys/devices/pci0000:00/0000:00:07.0/0000:1a:00.0/host2/rport-2:0-0/target2:0:0/2:0:0:0/rescan
/sys/devices/pci0000:00/0000:00:07.0/0000:1a:00.0/host2/rport-2:0-1/target2:0:1/2:0:1:0/rescan
#kick off rescan by updating rescan file in each port
echo 1 > /sys/devices/pci0000:00/0000:00:03.0/0000:15:00.0/host1/rport-1:0-0/target1:0:0/1:0:0:0/rescan
echo 1 > /sys/devices/pci0000:00/0000:00:03.0/0000:15:00.0/host1/rport-1:0-1/target1:0:1/1:0:1:0/rescan
echo 1 > /sys/devices/pci0000:00/0000:00:07.0/0000:1a:00.0/host2/rport-2:0-0/target2:0:0/2:0:0:0/rescan
echo 1 > /sys/devices/pci0000:00/0000:00:07.0/0000:1a:00.0/host2/rport-2:0-1/target2:0:1/2:0:1:0/rescan
# messages log  file show that  the new size was detected.
>tail -f /var/log/messages
Sep 19 09:56:10 server1 kernel: sd 1:0:1:0: [sdc] 12884901888 512-byte logical blocks: (6.59 TB/6.00 TiB)
Sep 19 09:56:10 server1 kernel: sdc: detected capacity change from 5497558138880 to 6597069766656
Sep 19 10:05:57 server1 kernel: sd 1:0:0:0: [sdb] 15032385536 512-byte logical blocks: (7.69 TB/7.00 TiB)
Sep 19 10:05:57 server1 kernel: sdb: detected capacity change from 6597069766656 to 7696581394432
Sep 19 10:05:57 server1 kernel: sd 1:0:1:0: [sdc] 15032385536 512-byte logical blocks: (7.69 TB/7.00 TiB)
Sep 19 10:05:57 server1 kernel: sdc: detected capacity change from 6597069766656 to 7696581394432
Sep 19 10:05:57 server1 kernel: sd 2:0:0:0: [sdd] 15032385536 512-byte logical blocks: (7.69 TB/7.00 TiB)
Sep 19 10:05:57 server1 kernel: sdd: detected capacity change from 6597069766656 to 7696581394432
Sep 19 10:05:58 server1 kernel: sd 2:0:1:0: [sde] 15032385536 512-byte logical blocks: (7.69 TB/7.00 TiB)
Sep 19 10:05:58 server1 kernel: sde: detected capacity change from 6597069766656 to 7696581394432

Friday, March 2, 2012

Control ISC DHCP to allocate IP address based on vendor ID

ISC DHCP supports conditional evaluation(man dhcp-eval), one of the evaluation expressions is hardware, the MAC  address of the network card.
Conditional evaluation make it possible to allocate different IP pool for clients or even allow multiple DHCPD daemons running in the same broadcasts domain.
My challenge is to setup a new DHCP server to PXE boot VMware Vms without affecting an existing DHCP server.
The solution is to create a new class which only response DHCP request  from Vmware NICs, the key is to use expression binary-to-ascii (16, 8, ":", substring (hardware, 1, 3)) to get the vendor ID.
$cat /etc/dhcpd.conf
ddns-update-style none;
ignore client-updates;
#log-facility local7;
#log (debug, binary-to-ascii (16, 8, ":", substring (hardware, 1, 3)));
class "vmware-nics"
{
match if  ( binary-to-ascii (16, 8, ":", substring (hardware, 1, 3)) = "0:05:69") or ( binary-to-ascii (16, 8, ":", substring (hardware, 1, 3)) = "0:0c:29") or ( binary-to-ascii (16, 8, ":", substring (hardware, 1, 3)) = "0:1c:14") or ( binary-to-ascii (16, 8, ":", substring (hardware, 1, 3)) = "0:50:56");
}
subnet 192.168.100.0 netmask 255.255.255.0 {
pool {
allow members of "vmware-nics";
option routers                  192.168.100.254;
option subnet-mask              255.255.255.0;
option domain-name              "example.com";
option domain-name-servers      192.168.100.1;
range dynamic-bootp 192.168.100.1 192.168.100.200;
#time unit is 1 sec
default-lease-time 3000;
max-lease-time 6000;
next-server 192.168.100.1;
filename "gpxelinux.0";
}
}

NOTE: the double 0  in MAC address  will be translated to single 0. e.g "00:05:69" = "0:05:69"
Troubleshooting:
If the expression doesn't work, you can check the expression by logging it to a file.You might need to disable "allow members" restriction in order for the expression to be logged.
log-facility local7;
log (debug, binary-to-ascii (16, 8, ":", substring (hardware, 1, 3)));

By default, DHCP log is directed to /var/log/message, it seems, in order to log expression, the DHCP must use separate log file. Because “local7.* /var/log/boot.log” is configured in /etc/syslogd.conf  by default, “log-facility local7” in dhcpd.conf will direct messages to /var/log/boot.log

Saturday, February 11, 2012

Enable timestamp logging in bash commands history

Bash has the built-in feature to support timestamp in history command , but it is not enabled by default in Red Hat Linux(ksh doesn’t have the feature at all)
It is recommended to tune two environment variables for history command to tighten audit.
1.Enable timestamp in command history
2.Increase the default  history file size
Enable timestamp in command history
Just need to set HISTTIMEFORMAT env variable, e.g.  HISTTIMEFORMAT="[%F %T %Z] "
The time format is the same as that of date command.
Increase the default history file size
There are two environment variables  for history size.
HISTSIZE: How many lines to keep in memory for current bash session, commands in current session are appended to ~/.bash_history on quitting.
HISTFILESIZE: How many lines to keep in history file ~/.bash_history
Both HISTSIZE and HISTFILESIZE seem to be 1000 by default, HISTSIZE=1000 is ok for current session, but HISTFILESIZE=1000 is too small to log enough commands for any past login session.
Both environment variables  are to be enabled for all users,  they can be put in global profile /etc/profile , but user defined global profile in /etc/profile.d/ is a better option.
For example, create a user global profile in /etc/profile.d
$cat /etc/profile.d/user.sh 
HISTSIZE=1000
HISTFILESIZE=40000
HISTTIMEFORMAT="[%F %T %Z] "
export HISTSIZE HISTFILESIZE HISTTIMEFORMAT
#With timestamp enabled, the history command output looks like this
$history 
19  [2012-02-03 13:41:56 EST] history
20  [2012-02-03 13:42:58 EST] date
22  [2012-02-03 13:42:55 EST] pwd

You may notice that the commands was not sorted by the time order, it is because, even “pwd” was executed  before date, but  it is was in different session and the “pwd session” was terminated after the “date session”, so the “pwd” command was appended after “date”.

To view all 40000 lines in ~/.bash_history for tracing very old commands, you need to temporarily increase HISTSIZE to 40000 before run “history”.  You can set the default HISTSIZE is 4000, but it takes too long to process for history command used in daily basis.

Other useful history related commands

#clear commands history in current session 
$history -c
#disable logging history commands
$set +o history 
#enable logging history commands
$set –o history 
#fc (fix command) 
#open last 4 commands in an editor and re-execute them after closing the editor
#it is useful if you need to re-execute more than one command
$fc -4 -1

Tuesday, October 11, 2011

Advanced RPM topics

Query
“queryformat”  option can query every piece information of a rpm package, the  information tags (macros ) are returned  by “rpm –querytags” command
#list top 2 rpm packages sorted by installation time
$rpm -qa  | xargs -I{} rpm -q --queryformat "{}        %{installtime}\n" {} | sort -rn -k2 | head -2
collectl-3.5.1-1        1317864013
git-1.7.4.1-1.el5        1316484590
#unfortunately the time returned is unixtime.  You can convert it to human readable format by  “date –d @timestring” e.g 
$date -d @1317864013
Thu Oct  6 12:20:13 EST 2011
#but there is a shortcut  “--last”
$ rpm -qa --last  | head -2
collectl-3.5.1-1                              Thu 06 Oct 2011 12:20:13 PM EST
git-1.7.4.1-1.el5                             Tue 20 Sep 2011 12:09:50 PM EST

"rpm -qa" supports regular expression itself, rather than pipe to grep e.g “rpm -qa | grep perl”
“rpm –qa perl\*” also works. There is no improvement on speed but typing become lesser.
requires and provides
#You can check the package dependency before install the package
$ rpm -qp --requires git-1.7.6-1.el5.rf.i386.rpm
..
libssl.so.6 
#To meet the dependency, you want to check who provides libssl.so.6 
$yum whatprovides libssl.so.6
openssl-0.9.8e-20.el5.i686 : The OpenSSL toolkit
Repo        : base
Matched from:
Other       : libssl.so.6
#if openssl has been installed, “rpm -q –whatprovides” can also provide the answer
$rpm -q --whatprovides libssl.so.6
openssl-0.9.8e-12.el5_4.6

rpm scriptlets

#query all nopre|nopost|nopreun|nopostun  scripts
$rpm -q --scripts xinetd
postinstall scriptlet (using /bin/sh):
if [ $1 = 1 ]; then
/sbin/chkconfig --add xinetd
fi
preuninstall scriptlet (using /bin/sh):
if [ $1 = 0 ]; then
/sbin/service xinetd stop > /dev/null 2>&1
/sbin/chkconfig --del xinetd
fi
postuninstall scriptlet (using /bin/sh):
if [ $1 -ge 1 ]; then
/sbin/service xinetd condrestart >/dev/null 2>&1
Fi
#query postinstall script only
$ rpm -q --queryformat "%{POSTIN}"  xinetd
if [ $1 = 1 ]; then
/sbin/chkconfig --add xinetd
#Don’t run the scripts during install/remove
rpm –i –noscripts|nopre|nopost|nopreun|nopostun   pkgname
rpm –e –noscripts|nopre|nopost|nopreun|nopostun   pkgname

Extract rpm contents without install

#use rpm2cpio to extract everything
$mkdir /tmp/epel
$ cd /tmp/epel
$ rpm2cpio /root/epel-release-5-4.noarch.rpm | cpio -ivd
./etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL
..
#use rpm2cpio to extract particular file
$rpm2cpio /root/epel-release-5-4.noarch.rpm | cpio -ivd  ./usr/share/doc/epel-release-5
#another way is to use rpm install with alternative root
$ rpm --root /tmp/epel/ -ivh  --nodeps /root/epel-release-5-4.noarch.rpm
Recover corrupted rpm database
Build RPM from source file

Thursday, September 15, 2011

Get information for inode or block of a file and vice versa

Debugfs can retrieve a file’s inode or block information and vice versa, it is provided by e2fsprogs package, which should be installed by default.
Find a file’s information for inode or block
#find a file’s inode id by ls, the sample file’s inode number is 12
$ls -li /boot/message
12 -rw-r--r-- 1 root root 80032 Mar 13  2009 /boot/message
#find a file’s inode or block info by debugfs
$echo "stat message" | debugfs /dev/sda1
debugfs 1.39 (29-May-2006)
debugfs:  Inode: 12   Type: regular    Mode:  0644   Flags: 0x0   Generation: 3354433043
User:     0   Group:     0   Size: 80032
File ACL: 4640    Directory ACL: 0
Links: 1   Blockcount: 162
Fragment:  Address: 0    Number: 0    Size: 0
ctime: 0x4e2371f6 -- Mon Jul 18 09:36:22 2011
atime: 0x49b95d4d -- Fri Mar 13 06:06:53 2009
mtime: 0x49b95d4d -- Fri Mar 13 06:06:53 2009
BLOCKS:
(0-11):7681-7692, (IND):7693, (12-78):7694-7760
TOTAL: 80
Find a file based on inode or block info
#find a file based on inode number by find, but it may take long time to search
$find /boot/ -inum 12
/boot/message
#find a file based on inode number by debugfs
$echo -e "ncheck 12" | debugfs /dev/sda1
debugfs:  Inode Pathname
12    /message
##find a file based on block number by debugfs
#use icheck to find inode number based on block number first
$echo -e "icheck 7693 " | debugfs /dev/sda1
debugfs:  Block Inode number
7693  12
#then use ncheck find the file by inode number
$echo -e "ncheck 12 " | debugfs /dev/sda1
debugfs:  Inode Pathname
12    /message

Wednesday, June 8, 2011

Create a shell script to display progress meter like wget's meter style

The following is a shell script to display progress meter like wget's meter style
The shell script output
$./meter.sh 
27 % |======================>                                                                   |
The shell script source code
$cat ./meter.sh
#!/bin/ksh
#Given start number and end number, display  progress meter and percentage like wget's style
start=1
#end=333
end=33
scale=$(($end/100.0))
for i in {$start..$end}
do
m1=$(($i / $scale)); m2=$(( ($end - $i ) / $scale ))
integer m1; integer m2
#fill 2 segments of variable length  with zeros
str=$( printf "%0${m1}d %s %0${m2}d\n"   0 ">" 0  ) 
str="|$str|"
#replace first segment zeros with '=' 2nd segment zeros with space then re-join
str1=$(echo $str | awk -F' > ' '{ print $1 }'); str1=${str1//0/=}
str2=$(echo $str | awk -F' > ' '{ print $2 }'); str2=${str2//0/' '}
str="${str1}>${str2}"
pct=$(($i * 100 / $end ))
#Beautify the final loop 
[ $i -eq $end ] && str=$(echo $str | sed -e 's/ /=/g' -e 's/>/=/g' -e 's/0/=/g' )
print -n " \\r ${pct} % $str "
sleep 1
done
printf "\n"

Wednesday, July 7, 2010

Master Bash command line

You may already know the bash shortcut keys: CTL+A/CTL+E/CTL+R ... , but do you know how the shortcut keys are defined and any other useful shortcut keys?
The functions of short keys come from readline library, bash seems to be the only shell supports readline.
In addition to the shell capability, its editing mode has to be set to emacs instead of vi

$set -o | egrep '^vi | ^emacs'
emacs           on
vi              off

To check current key bindings:
$bind -p | grep  \[CM]
…
"\M-.": yank-last-arg
"\M-_": yank-last-arg
"\M-\C-y": yank-nth-arg
"\M-y": yank-pop
The text C-k is read as `Control-y', Control is Ctrl key.
The text M-k is read as `Meta-k', Meta key is ESC/ALT key
The following is not a complete list of short keys,check
readline readme for a complete list)

Example command:

$ echo one two three
one two three
TASK #1 paste the last argument: the word “three”
m-. insert last argument of the previous command( special variable $_ also refer to last argument, it works for ksh/bash)


TASK #2 paste the 1st argument or the command.
m-c-y : to paste 1st argument “one”


TASK #3 paste the command or the nth argument
m-2-m-c-y : to paste the 2nd argument “two”;

m-0-m-c-y : to paste the command “echo” itself.

TASK #4 delete word “three” to change it to “echo one two”
Step #1) Retrieve last command:
Use either of thee options: Up arrow key ; c-p key ; c-r key to search, keep pressing c-r to find the next match
Step #2) Delete the word.
c-w Delete from the cursor to the previous whitespace(you don’t need to type backspace five times to delete the word)
m-d is the opposite of c-w is , so to delete “echo”; the key sequence will be c-p c-a m-d

Less used text keys to cut text: c-k and c-u
C-k Kill the text from the current cursor position to the end of the line
C-u Kill backward from the cursor to the beginning of the current line.
To delete text “echo one”: c-p m-b m-b c-u (m-b is to back one word)


TASK #5 swap “three” “two” change it to “echo one three two”
c-p m-b c-w c-e c-y the key-point is to cut (c-w) word “two” and paste(c-y) it to end of line


TASK #6 undo the changes
m-r Undo all changes made to this line
c-_ Incremental undo, separately remembered for each line


###Other shell tips
CDPATH: directory search path Instead of typing full path, firstly adding the parent dir to CDPATH ENV variable(save it to .profile for permanent change), then cd dir-name will go to the dir
$ export CDPATH=/var/log/
$cd audit
/var/log/audit
OLDPWD: - is equivalent to $OLDPWD; When it is used as the operand, this shall be equivalent to the command:
cd "$OLDPWD" && pwd ; (reference man ksh or man bash)


$cd /tmp
$cd /var/tmp
$cd -
/tmp
DIRS
“-“ only remember last dir, for dirs >2 , you can use “pushd .” to remember any number of dirs;
the dir names can be displayed with “dirs” command or go to the last dir with “popd” command

Tuesday, March 23, 2010

Less known Linux commands.

Completing a task with the simplest command.

#ac prints out a report of connect time (in hours) based on the logins/logouts in the current wtmp file. A total is also printed out

$ac -p
root                                532.96
admin                               63.53
total     536.96

# mcookie generates a 128-bit random hexadecimal number
#The "random" number generated is actually the output of the MD5 message digest fed with various piece of random information: the current time, the process id, the parent process id ..
$mcookie
9612f5db846dd4d0655572b33ea1cb6f

#pidof -- find the process ID of a running program.
##match program name only, it can't match argument of the program
$ pidof /sbin/mingetty
3773 3770 3769 3768 3767 3766

# procinfo :display memory, disk, IRQ & DMA module and device info #$procinfo -D refresh values every few seconds just like top.
$procinfo
Memory:      Total        Used        Free      Shared     Buffers
Mem:       3897500      684240     3213260           0      269308
Swap:       779112           0      779112

Bootup: Wed Feb 24 00:20:02 2010    Load average: 0.11 0.07 0.02 3/223 5641

user  :       0:54:16.96   0.2%  page in :     103469  disk 1:    10272r 1857163w
nice  :       0:00:28.10   0.0%  page out:   12920948
system:       3:13:02.34   0.6%  page act:     126534
IOwait:       0:11:44.80   0.0%  page dea:          0
hw irq:       0:00:08.20   0.0%  page flt:   84232828
sw irq:       1:30:52.17   0.3%  swap in :          0
idle  :  22d  9:49:49.93  98.9%  swap out:          0
uptime:  22d 15:38:40.56         context : 1476505392

irq  0: 489275054 timer                 irq  9:         0 acpi         
irq  1:         8 i8042                 irq 12:       105 i8042        
irq  3:         1                       irq 14:  17590508 ide0         
irq  4:         1                       irq169:   7179622 ioc0, vmxnet ether
irq  6:         5                       irq177:   3543610 vmxnet ether 
irq  7:         0 parport0              irq185:     42843 vmxnet ether 
irq  8:         2 rtc                   irq193:  15376791 vmxnet ether 

#readlink - display destination of a symbolic link
$ls -l test2
lrwxrwxrwx 1 root wheel 5 2010-03-19 10:09 test2 -> test1
$readlink test2
test1
#Who links me? find source softlink with "lname" argument
$ touch /var/tmp/test1
$ ln -s /var/tmp/test1 /tmp/test1
$ find /tmp -lname /var/tmp/test1 -ls
11    0 lrwxrwxrwx   1 root wheel          14 Jun 30 11:07 /tmp/test1 -> /var/tmp/test1

#Who links me? find source hardlink with "samefile" argument
#hardlinks have same inode number(inode=13316 in this example), so it can also be achived with inum argument as well.
$touch /tmp/test1/test-hl
$ln  /tmp/test1/test-hl /tmp/test-hl
$find /tmp/ -samefile /tmp/test1/test-hl -exec ls -il {} \;
13316 -rw-r--r-- 2 root  wheel 0 2010-06-30 11:15 /tmp/test1/test-hl
13316 -rw-r--r-- 2 root wheel 0 2010-06-30 11:15 /tmp/test-hl


# seq - print a sequence of numbers
# default increment is 1
# It was used in "for loop", but now brace expansion {1..3} is better choice.

$seq
1
2
3
$seq -s " "  3
1 2 3

#convert vertical lines to horizontal lines

$ seq 4 | paste -s
1       2       3       4

$ seq 4 | xargs -n 2
1 2
3 4

#convert horizontal lines to vertical lines
$echo "123456"| fold -w 2
12
34
56

#stat - display file or file system status
##Links:2 means the file has two copies(hard link files)
$stat test1
File: `test1'
Size: 3               Blocks: 8          IO Block: 4096   regular file
Device: fd04h/64772d    Inode: 767061      Links: 2
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2010-03-18 16:21:01.000000000 +1100
Modify: 2010-03-18 16:21:00.000000000 +1100
Change: 2010-03-18 16:21:00.000000000 +1100

##display parent file system info.It can be used to find parent partition by matching inodes Total/Free of df -i
$stat -f test1
File: "test1"
ID: 0        Namelen: 255     Type: ext2/ext3
Block size: 4096       Fundamental block size: 4096
Blocks: Total: 2633708    Free: 2371194    Available: 2237409
Inodes: Total: 1338240    Free: 1335916

#tac - concatenate and print files in reverse
$cat t1
12
$ tac t1
21

#usleep - sleep for the specified number of microseconds
usleep 300

#watch - execute a program periodically, showing output fullscreen
#monitor eth0 output, refresh every 2 seconds
watch -n 2 ifconfig eth0

#Zdump prints the current time in each zone name named on the command line.
$date
Thu Mar 18 05:51:55 GMT 2010
$zdump GMT
GMT  Thu Mar 18 05:51:57 2010 GMT
(alternative command: $export TZ=GMT;date)

#zgrep - search possibly compressed files (.Z,gz,bz2)for a regular expression
#other z commands zcat zmore ...
$zgrep .*  test1.gz
test1.gz:test message

#shell tips
# - is equivalent to $OLDPWD;When a is used as the operand,this shall be equivalent to the command: cd "$OLDPWD" && pwd ; (reference man ksh or man bash)

$cd /tmp
$cd /var/tmp
$cd -
/tmp

# "$_" .. expands to to the last argument to the previous command.. (reference Special Parameters in man ksh/bash)
# ( bash only "!$" "!!:$" designates the last argument of the preceding command. This may be shortened to "!$")
$ ping -c 1 172.16.1.1
PING 172.16.1.1 (172.16.1.1) 56(84) bytes of data.
64 bytes from 172.16.1.1: icmp_seq=1 ttl=64 time=0.396 ms
$ telnet $_ 80
Trying 172.16.1.1...
Connected to 172.16.1.1.
Escape character is '^]'.
^]
telnet> quit
Connection closed.

Wednesday, November 4, 2009

How to exclude directories with find

To exclude directories with find,grep is the obvious choice  but it is not efficient.Following shows three ways to exclude directories with find

#Sample directories and file, the aim is to exclude directory /tmp/test/test1

$find /tmp/test
/tmp/test
/tmp/test/test1
/tmp/test/test1/test1.file
/tmp/test/test2
/tmp/test/test2/test2.file
/tmp/test/test3

(1) Simple most efficient way, but I can only get it working in ksh

$find /tmp/test/!(test1) -type f
/tmp/test/test2/test2.file
/tmp/test/test3

(2)With not expression “! “

$find /tmp/test ! -path "/tmp/test/test1*" -type f
/tmp/test/test2/test2.file
/tmp/test/test3

(3)With prune, which means exclude preceding path

$find /tmp/test  -path  /tmp/test/test1 -prune  -o -type f -print
/tmp/test/test2/test2.file
/tmp/test/test3


Thursday, June 25, 2009

few scripting tips.



How to get the last digits of a string e.g print 201 for string ua07app201?


#sed back reference: print the first match pattern enclosed by ( )
echo ua07app201 | sed 's/.*[^0-9]\([0-9]*\)$/\1/'

#Sed delete: Delete the longest match of non-digits char
echo 'ua07app201' | sed 's/.*[^0-9]//'

#Expr matching operator : Similar to sed back reference, without (), it returns the the number of matched chars.
expr ua07app201 : '.*[^0-9]\([0-9]*\)$'

#Awk: set non-digit as seperator, print the last filed $NF
echo 'ua07app201' | nawk -F'[^0-9]' '{print $NF}'

#Perl in command line mode
echo ua07app201 | perl -nle ' $_ =~m /(\d+$)/; print $1'
or the simplizied version
echo ua07app201|perl -nle'print/(\d+)$/'

#Parameter Substitution, delete the longest match of non-digits chars from beginning.
a='ua07app201';echo "${a##*[!0-9]}"


How to get path only from full path of a file?


#Parameter Substitution, delete the shortest match from end
$ var=/var/tmp/test.txt;echo ${var%/*}
/var/tmp


How to sort a string?


#one-liner to sort a string
$echo "s03 s08 s01" | tr '[:space:]' '\n' | sort -n | paste -s
s01     s03     s08