Showing posts with label grep. Show all posts
Showing posts with label grep. Show all posts

Tuesday, September 26, 2017

Forcing a fuse (sshfs) network fileshare to unmount in OSX

As some of you already know, I do have an old MacBook Air which I use as my main (as in the computer I sit in front of, not the computer I store data on. Laptops can be stolen, you know) machine until I find a new Linux laptop replacement. For this reason I need it to play nice with other machines, and that requires sometimes to mount a fileshare. If the other host is in the same VLAN, that is rather easy because there are ways to mount a Windows (SMB/CIFS) and even a Linux/UNIX (nfs) fileshare without breaking a sweat. But what if the machine is remote? If we can ssh into it, why not then use sshfs?

As we are aware of (since we read the link. There are a few more sshfs examples here), sshfs requires fuse. Since I am using OSX, which at the present time does not have it, I need to install. If you are curious, the one I use is FUSE for MacOS.

Mounting: business as usual

Let's say we are in the machine boris as user pickles trying to mount my home directory off desktop. We create the mountpoint (Let's use /tmp/D or ~/D so it looks more like what we would do in Linux:

boris:Documents pickles$ mkdir /tmp/D; sshfs raub@desktop.in.example.com:. /tmp/D
boris:Documents pickles$ df -h
Filesystem                     Size   Used  Avail Capacity  iused    ifree %iused  Mounted on
/dev/disk1                    112Gi   79Gi   33Gi    71% 20783599  8546848   71%   /
devfs                         364Ki  364Ki    0Bi   100%     1259        0  100%   /dev
map -hosts                      0Bi    0Bi    0Bi   100%        0        0  100%   /net
map auto_home                   0Bi    0Bi    0Bi   100%        0        0  100%   /home
raub@desktop.in.example.com:.  492Gi  389Gi  102Gi    80%   408428 32359572    1%   /private/tmp/D
boris:Documents pickles$

So far so good. To unmount it we can use diskutil, as in (Mac)

boris:Documents pickles$ diskutil umount /tmp/D
Unmount successful for /tmp/D
boris:Documents pickles$

or (Linux)

fusermount -u /tmp/D

Or go old school (both):

sudo mount /tmp/D

Since boris is a laptop, sometimes if we just let it go to sleep it will unmount it. Then, all we have to do is mount it again.

Mounting again: not so fast

Thing is, sometimes it does not work.

boris:Documents pickles$ mkdir /tmp/D; sshfs raub@desktop.in.example.com:. /tmp/D
mkdir: /tmp/D: File exists
fuse: bad mount point `/tmp/D': Input/output error
boris:Documents pickles$ 

Ok, maybe it did not automagically unmounted while laptop was off. So, let's tell it to do so:

boris:Documents pickles$ diskutil umount /tmp/D
Unmount failed for /tmp/D
boris:Documents pickles$ 

Just before you ask, sudo mount /tmp/D did not work either. What if the old sshfs processes did not cleanly closed and as a result are still lingering? To answer that we must elicit some help from one of grep's cousins, pgrep:

boris:Documents pickles$ pgrep -lf sshfs
384 sshfs raub@desktop.in.example.com:. /tmp/D
1776 sshfs raub@desktop.in.example.com:. /tmp/D
7356 sshfs user@other.in.example.com:. /tmp/D
boris:Documents pickles$

Just as we guessed, there are not only but quite a few unhappy sshfs instances. Let's see if we can kill them:

boris:Documents pickles$ kill 384 1776 7356
boris:Documents pickles$ pgrep -lf sshfs
384 sshfs raub@desktop.in.example.com:. /tmp/D
1776 sshfs raub@desktop.in.example.com:. /tmp/D
boris:Documents pickles$ kill 384
boris:Documents pickles$ pgrep -lf sshfs
384 sshfs raub@desktop.in.example.com:. /tmp/D
1776 sshfs raub@desktop.in.example.com:. /tmp/D
boris:Documents pickles$ kill 1776
boris:Documents pickles$ pgrep -lf sshfs
384 sshfs raub@desktop.in.example.com:. /tmp/D
1776 sshfs raub@desktop.in.example.com:. /tmp/D
boris:Documents pickles$
Hmmm, this is going nowhere slowly. Let's crank up a notch and force it to kill the mount.
boris:Documents pickles$ kill -9 1776
boris:Documents pickles$ pgrep -lf sshfs
384 sshfs raub@desktop.in.example.com:. /tmp/D
boris:Documents pickles$ kill -9 384
boris:Documents pickles$ pgrep -lf sshfs
\boris:Documents pickles$

Sounds like we got them all. Now, let's try and mount once more:

boris:Documents pickles$ mkdir /tmp/D; sshfs raub@desktop.in.example.com:. /tmp/D
mkdir: /tmp/D: File exists
raub@desktop.in.example.com's password:
boris:Documents pickles$

I think we have a winner!

Tuesday, November 10, 2015

Memory size and Memory location in Linux

Quick easy post: I right now need to find (I am tying this as I am solving the problem, so this will be a rough post) how many memory slots the motherboard of a machine running Linux (actually Xenserver, but close enough for our needs) has, which ones are being occupied, and which kind of SIMM cards it is using. This machine is in a server room about a mil from me am I do not want to go face the rain to get there. So, how to do the deed?

The Xencenter interface does not seem to be helpful with that, so we will don our battle moustaches (ladies, it is ok to buy a nice handlebar moustache to use in this occasions; the look of your coworkers should be reason enough to do it) and go to command line.

The command in question is dmidecode, which can be found in most Linux distros to probulate the system management BIOS. Some of you have used it before, so let's rush through it a bit. This is how it starts:

# dmidecode 2.11
SMBIOS 2.7 present.
77 structures occupying 4848 bytes.
Table at 0xCF42C000.

Handle 0xDA00, DMI type 218, 11 bytes
OEM-specific Type
        Header and Data:
                DA 0B 00 DA B2 00 17 20 0E 10 01

Handle 0x0000, DMI type 0, 24 bytes
BIOS Information
        Vendor: Dell Inc.
        Version: 2.3.3
        Release Date: 07/10/2014
        Address: 0xF0000
        Runtime Size: 64 kB
        ROM Size: 8192 kB
        Characteristics:
                ISA is supported
                PCI is supported
                PNP is supported
                BIOS is upgradeable
                BIOS shadowing is allowed
                Boot from CD is supported
                Selectable boot is supported
                EDD is supported
                Japanese floppy for Toshiba 1.2 MB is supported (int 13h)
                5.25"/360 kB floppy services are supported (int 13h)
                5.25"/1.2 MB floppy services are supported (int 13h)
                3.5"/720 kB floppy services are supported (int 13h)
                8042 keyboard services are supported (int 9h)
                Serial services are supported (int 14h)
                CGA/mono video services are supported (int 10h)
                ACPI is supported
                USB legacy is supported
                BIOS boot specification is supported
                Function key-initiated network boot is supported
                Targeted content distribution is supported
                UEFI is supported
        BIOS Revision: 2.3

As you can see, the machine in question is a Dell (they do make servers you know; this one is a 1U) and we can see some of its specs. Next would be stuff like CPU specs (cache, features, speed), which we don't care right now. What we care about is the memory:

Memory Device
        Array Handle: 0x1000
        Error Information Handle: Not Provided
        Total Width: 72 bits
        Data Width: 64 bits
        Size: 16384 MB
        Form Factor: DIMM
        Set: 1
        Locator: DIMM_A1
        Bank Locator: Not Specified
        Type: DDR3
        Type Detail: Synchronous Registered (Buffered)
        Speed: 1600 MHz
        Manufacturer: 00CE00B300CE
        Serial Number: 0296F2E0
        Asset Tag: 01150664
        Part Number: M393B2G70EB0-YK0
        Rank: 2
        Configured Clock Speed: 1333 MHz

Handle 0x1101, DMI type 17, 34 bytes
Memory Device
        Array Handle: 0x1000
        Error Information Handle: Not Provided
        Total Width: 72 bits
        Data Width: 64 bits
        Size: 16384 MB
        Form Factor: DIMM
        Set: 1
        Locator: DIMM_A2
        Bank Locator: Not Specified
        Type: DDR3
        Type Detail: Synchronous Registered (Buffered)
        Speed: 1600 MHz
        Manufacturer: 00CE00B300CE
        Serial Number: 0296F43E
        Asset Tag: 01150664
        Part Number: M393B2G70EB0-YK0
        Rank: 2
        Configured Clock Speed: 1333 MHz

Handle 0x1102, DMI type 17, 34 bytes
Memory Device
        Array Handle: 0x1000
        Error Information Handle: Not Provided
        Total Width: 72 bits
        Data Width: 64 bits
        Size: No Module Installed
        Form Factor: DIMM
        Set: 2
        Locator: DIMM_A3
        Bank Locator: Not Specified
        Type: DDR3
        Type Detail: Synchronous
        Speed: Unknown
        Manufacturer:
        Serial Number:
        Asset Tag:
        Part Number:
        Rank: Unknown
        Configured Clock Speed: Unknown

Handle 0x1103, DMI type 17, 34 bytes
Memory Device
[...]

As you can see, we have a 16GB SIMM (fine, be grammar police and call it a DIMM) on DIMM_A1 amd DIMM_A2 slots, but nobody on DIMM_A3; just between us, this machine only has those 2 SIMMs. So, how about we find out how many SIMM slots this machine have?

[root@vmhost3 ~]# dmidecode | grep 'Locator: DIMM_'
        Locator: DIMM_A1
        Locator: DIMM_A2
        Locator: DIMM_A3
        Locator: DIMM_A4
        Locator: DIMM_A5
        Locator: DIMM_A6
[root@vmhost3 ~]#

Hmm, we can do better; let's be lazy and let the script do the count. And, just to show we are good, we will use sed instead of grep because the name is shorter

[root@vmhost3 ~]# dmidecode | sed -n '/Locator: DIMM_/p'|wc -l
6
[root@vmhost3 ~]#

Six slots. Not bad. So, how many of those are being populated? We know that an empty slot is flagged by Size: No Module Installed. Let's then look for the entries without that pattern, which is easy to do using grep:

[root@vmhost3 ~]# dmidecode | grep -A5 'Memory Device' | grep -c 'MB'
2
[root@vmhost3 ~]#

Note we dropped the wc since grep can count how many times we got successful matches. Also, the -A5 means that we are printing the first 5 lines after the matched pattern; this way the second grep has something to bite. How about if we spit out the name of which memory slots have memory and how big they are? And maybe the type and model number while we are at it. Here's how to do the deed using grep:

[root@vmhost3 ~]# dmidecode |  grep -A18  'Memory Device' | grep -B4 -A13 -e 'Size:.* MB' | grep -e 'Locator: D' -e 'Size' -e 'Part Number'
        Size: 16384 MB
        Locator: DIMM_A1
        Part Number: M393B2G70EB0-YK0
        Size: 16384 MB
        Locator: DIMM_A2
        Part Number: M393B2G70EB0-YK0
[root@vmhost3 ~]# 

I used 3 greps here to make it easier to see what is going on:

  1. Fist grep finds from the dmidecode output the entries related to memories and feed the complete entry (each is 18 lines long) to the next grep.
  2. This one then only looks for entries that have memories being reported in megabytes (MB); the fragile assumption here is that if there is a SIMM in the slot, its Size: will be reported as X MB, otherwise as we found out above it will be Size: No Module Installed. The cleverest way to do this is to test for Size: No Module Installed; if it is not there use it. But, I never claimed to be that clever.

    Now, if a matching pattern is found, we print the entire entry for this memory device, hence the -A13 (after) and -B4 (before); they print the lines before and after the one which contains the pattern.

  3. Finally we print only the lines we want to use, namely Part Number, Size, and Locator(which SIMM slot memory is sitting on).

Now, I know how many memory slots are available, which ones are being occupied, and which memory card models are installed. I can now decide if I want to buy more matching ones or lookup the specs and find the largest cards that will work in this device. Not bad for a rainy day.

Thursday, May 28, 2015

Save/Suspend and Resume a VMware ESXi vm client command line style

Here is an interesting project: let's say you have one or more UPS (one per power supply) attached to your ESXi vm host (or hosts; this is completely scalable). Yes, it goes without saying providing uninterrupted power to your servers is a good idea. But, unless you are a large company chances are this power will only last so long. You can make it last even longer by having a plan that will decide in which order your physical servers will be shut down based on load and remaining power. That does mean shutting down your vm servers; for the sake of this discussion, we will assume they are ESXi-based.

I have seen interesting articles on shutting down ESXi hosts on case of power failure, but many assume you are monitoring the UPS through the ESXi host. That might be thinking small; what if that is not the case? What if you have a UPS or two on the bottom feeding the entire cabinet? Chances are you will be monitoring it from a host, be it a vm or not, that is running some monitoring program such as Nagios, that is set to do something in case of a power failure. Of course, if you have a monitoring vm you can talk to your UPS using either ethernet or USB passthrough depending on how sophisticated that model is. And it will decide when to tell our ESXi box it is time to shut down.

I do not know about you but I would like to gracefully save/shutdown the vm clients running in that host before that.

The plan is to have the host monitoring the UPS tell the ESXi host to run a shutdown procedure, which would need to first save the vm guests. And, once the vm server is back up and running, it would resume -- by its own accord or by the order of another server -- the saved vm clients. Yes, you will have to worry about how the monitoring and the ESXi hosts will talk to each other and how the client's clock will catch up, but for this article we will focus on creating a tool that only cares about saving and resuming all of the vm guests running in this ESXi box. We can expand later.

If we want to save the running vm clients, we probably should find out which ones are running. In a previous article we wrote a script to see if a given vm client is running, off, or saved. For the script we will be creating, we want to use something else, vmdumper. Here is what the help screen for the program says.

/tmp # vmdumper -h
vmdumper: [options]  
         -f: ignore vsi version check
         -h: print friendly help message
         -l: print information about running VMs
         -g: log specified text to the vmkernel log
/tmp #
Note the -l shows only the running vms, which is what we want to do. So, let's run that and see what it spits back (I will break them a bit so they will kinda fit the screen):
~ # /sbin/vmdumper -l
wid=264397      pid=-1  cfgFile="/vmfs/volumes/52a08b50-984b4bf0-219f-d067
e51ce7b7/boot2docker/boot2docker.vmx" uuid="56 4d 11 2b 63 bc 88 fb-d9 e1 
93 fc 69 36 66 45"  displayName="boot2docker"       vmxCartelID=264396
wid=13080       pid=-1  cfgFile="/vmfs/volumes/52a08b50-984b4bf0-219f-d067
e51ce7b7/Windows 2012/Windows 2012.vmx"       uuid="56 4d e7 cb 24 11 63 
13-04 0d 9b 41 08 f9 a3 be"  displayName="Windows 2012"      vmxCartelID=13079
wid=527962      pid=-1  cfgFile="/vmfs/volumes/52a08b50-984b4bf0-219f-d067
e51ce7b7/devcentos/devcentos.vmx"     uuid="56 4d d7 e8 25 6c de 91-09 38 
60 ce ab 5d 43 ca"  displayName="devcentos" vmxCartelID=527961
~ #
As you can see, it shows the path for the config file the vm guest is using (cfgFile, its name (displayName) and something called wid. And a few other things I do not feel like caring about. So, how do we save a vm anyway? We know we can start a vm using vim-cmd vmsvc/power.on, so maybe it sounds similar. Some frustrating searching later we find that http://www.vi-toolkit.com/wiki/index.php/Vmsvc/power.hibernate might be a candidate. Thing is it needs wmid as the argument. I will save some time and state (have faith, brother!) it can be obtained by
vim-cmd vmsvc/getallvms | grep "${displayName}" | awk '{ print "vmid=" $1}'
But, does it really work? We shall try with devcentos, which happens to have wmid=3 (again, I cheat because I have spent loads of time testing this):
/tmp # vim-cmd  vmsvc/power.hibernate 3
(vim.fault.ToolsUnavailable) {
   dynamicType = ,
   faultCause = (vmodl.MethodFault) null,
   msg = "Cannot complete operation because VMware Tools is not running in this virtual machine.",
}
/tmp #
And it does not seem to want to work. It needs VMware Tools, and I do not want to worry about it. So let's see what else we can use. After some looking I found vmdumper. To save devcentos we could do
/tmp # vmdumper 527962 suspend_vm
Suspending VM...
/tmp # 
The weird number 527962 is the world id or wid for devcentos, which happens to be the first column in the output of vmdumper -l associated with that vm client.

Pet Peeve: If you remember the output of vmdumper -h, which should be the help page for that command, mentions nothing about suspend-vm. Good job, VMware! That does make me wonder what else you are not documenting...

Now my venting is done, let's see what we need.

  1. We need the wid to shut down with vmdumper
  2. We can resume (I tested already, and so can you!) the vm client using vim-cmd vmsvc/power.on. Thing is it needs wmid as the argument, which we figure out how to get above.
  3. We then need a way to save wmid so when we can restore the saved vms. Probably saving the names of the vms would also be a nice touch.
So, here is the script I wrote to save and restore the running vms. As you can see, it is rather dumb since it is an all or nothing kinda deal. It is also unforgiving: if you run it again to save vms, the old /var/tmp/save_vms file will be overwritten. For what I wrote this script for, that is but a small annoyance.
cat > save_runningvms.sh  << 'EOF'
#!/bin/sh
IFS=$'\n'
USAGE="Usage: $0 {save|resume}"
SAVE_FILE=/var/tmp/save_vms

if [ "$#" == "0" ]; then
        echo "$USAGE"
        exit 1
fi

selection=$1

case $selection in
   # If we want to save them
   save )
      rm -f ${SAVE_FILE}

      # Find which vms are currently running
      for i in $(vmdumper -l \
         | awk ' BEGIN { FS = "\t" }; { print $1 ";" $5 }')
      do
         eval $i
         # Start saving them
         vmid=$(vim-cmd vmsvc/getallvms | grep "${displayName}" \
            | awk '{ print "vmid=" $1}')
         vmdumper $wid suspend_vm

         # Write list of saved guests in $SAVE_FILE
         echo $vmid ";" $i >> ${SAVE_FILE}
      done
      ;;
   # If we want to restore them
   resume )
      # Get list of saved guests
      for i in $(cat ${SAVE_FILE})
      do
         # Wake them up
         eval $i
         vim-cmd vmsvc/power.on $vmid
      done
      ;;
esac
EOF
chmod +x save_runningvms.sh
You will note that I avoid using Bashisms because the shell in busybox is closer to Bourne than Bash.

I think you probably want to see it running. So, let's run it. First we do some saving

/tmp # ./save_runningvms.sh save
Suspending VM...
Suspending VM...
Suspending VM...
/tmp # 
Did it create the /var/tmp/save_vms file? If so, how does it look like?
/tmp # cat /var/tmp/save_vms
vmid=24 ; wid=5718058;displayName="boot2docker"
vmid=23 ; wid=5714001;displayName="Windows 2012"
vmid=3 ; wid=5715871;displayName="devcentos"
/tmp # 
Ok, I am not convinced. You must be lying. Lemme go to the other vmhost, vmhost, and ping devcentos
[raub@vmhost tmp]# ping devcentos
PING devcentos.example.com (10.0.0.112) 56(84) bytes of data.
From vmhost.example.com (10.0.0.19) icmp_seq=2 Destination Host Unreachable
From vmhost.example.com (10.0.0.19) icmp_seq=3 Destination Host Unreachable
From vmhost.example.com (10.0.0.19) icmp_seq=4 Destination Host Unreachable
^C
--- devcentos.example.com ping statistics ---
7 packets transmitted, 0 received, +3 errors, 100% packet loss, time 6125ms
pipe 3
[raub@vmhost tmp]# 
Hmmmm, okay. But maybe it was off and you were lying to me. So, let's see about waking up the sleeping vms.
/tmp # ./save_runningvms.sh resume
Powering on VM:
Powering on VM:
Powering on VM:
/tmp #
And then pinging devcentos
[raub@vmhost tmp]# ping devcentos
PING devcentos.example.com (10.0.0.112) 56(84) bytes of data.
64 bytes from devcentos.example.com (10.0.0.112): icmp_seq=1 ttl=64 time=212 ms
64 bytes from devcentos.example.com (10.0.0.112): icmp_seq=2 ttl=64 time=0.316 ms
64 bytes from devcentos.example.com (10.0.0.112): icmp_seq=3 ttl=64 time=0.313 ms
^C
--- devcentos.example.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2078ms
rtt min/avg/max/mdev = 0.313/70.992/212.349/99.954 ms
[raub@vmhost tmp]#
I guess the script does work after all. What's the world coming to?

Friday, January 02, 2015

Monitoring Windows (firewall) log file without tail and grep

I like log files. A good log file can tell you a lot about what happened, be it whether a package was successfully installed, why a user could not check mail, or who tried to connect to our voip server. As a result I use log monitoring a lot on Linux/Unix/OSX. You'll always find me with a session running tail, and sometimes grep, against the appropriate log files. That's how I roll.

On Windows, it seems the status quo when something goes boink is to restart services or host, or hope the error message in the dialog box that popped up is useful enough to be googled. But, Windows has log files just like the other programs. Yes, a lot of application developers do not bother to write good logs for their apps, but the OS itself has a metric buttload of logs which might have caught error messages from those applications. So, let's talk a bit about those logs and how to monitor them. I will warn you that as I come from Unix/Linux, I am very command line-oriented, so expect this discussion to be a bit clickety-click challenged.

The way of the land

Windows does create quite a few log files and has directories (or folders if you will). Here is some of what I see in my rather boring default Windows 7 desktop:

C:\>dir Windows\*.log
 Volume in drive C has no label.
 Volume Serial Number is 705E-722F

 Directory of C:\Windows

12/21/2013  05:53 AM             1,774 DtcInstall.log
01/14/2014  02:15 PM             9,640 IE10_main.log
02/17/2014  07:21 PM            26,875 IE11_main.log
12/20/2013  07:19 PM             3,792 IE9_main.log
12/15/2014  07:39 PM             6,564 PFRO.log
12/15/2014  07:39 PM            16,716 setupact.log
07/13/2009  11:51 PM                 0 setuperr.log
12/21/2013  05:53 AM             1,313 TSSysprep.log
01/04/2015  02:07 AM         1,455,242 WindowsUpdate.log
               9 File(s)      1,521,916 bytes
               0 Dir(s)  14,102,495,232 bytes free

C:\>dir Windows\System32\LogFiles
 Volume in drive C has no label.
 Volume Serial Number is 705E-722F

 Directory of C:\Windows\System32\LogFiles

09/23/2014  02:35 AM    <DIR>          .
09/23/2014  02:35 AM    <DIR>          ..
07/14/2009  12:32 AM    <DIR>          Fax
07/13/2009  09:34 PM    <DIR>          Firewall
09/23/2014  02:35 AM    <DIR>          HTTPERR
12/15/2014  07:50 PM    <DIR>          Scm
12/21/2013  04:00 PM    <DIR>          SQM
07/14/2009  12:32 AM    <DIR>          Windows Portable Devices
07/13/2009  11:45 PM    <DIR>          WMI
07/13/2009  09:36 PM    <DIR>          WUDF
               0 File(s)              0 bytes
              10 Dir(s)  14,102,495,232 bytes free

C:\>

Let's say you want to probulate the WindowsUpdate.log file since it sounds interesting. You open it in notepad, which will get unhappy as it is rather large, or wordpad. Or get notepad++ which I personally recommend.

What if you want to see the file in the command line? The equivalent of the Unix/Linux/OSX cat command it type, but you really do not want to run it on that file. Trust me; I just did it and it scrolled long enough for me to write this and the last paragraph. That does not sound impressing but I am a slow typist. I even had time to get the link for notepad++. Next option is to use more, which is just like the same command in the other operating systems. So you would then be able to see (without them just zooming past your eyes) entries like

2014-12-17      00:54:32:864     920    a3c     Agent   Update {E0A75066-D16E-44
D0-8B6E-2B4708ABE781}.201 is pruned out due to potential supersedence
2014-12-17      00:54:32:864     920    a3c     Agent     * Added update {9FF3F8
7F-0DC5-4484-B757-37C4C25D4965}.201 to search result
2014-12-17      00:54:32:864     920    a3c     Agent     * Found 49 updates and
 77 categories in search; evaluated appl. rules of 1876 out of 2659 deployed ent
ities
2014-12-17      00:54:32:911     920    a3c     Agent   *********
2014-12-17      00:54:32:911     920    a3c     Agent   **  END  **  Agent: Find
ing updates [CallerId = AutomaticUpdates]
2014-12-17      00:54:32:911     920    a3c     Agent   *************
2014-12-17      00:54:32:942     920    a3c     Report  REPORT EVENT: {EFE8CD74-
F8C9-4D59-8F52-63D3EA18D227}    2014-12-17 00:54:32:895-0500    1       147
101     {00000000-0000-0000-0000-000000000000}  0       0       AutomaticUpdates
        Success Software Synchronization        Windows Update Client successful
ly detected 49 updates.
2014-12-17      00:54:32:942     920    a3c     Report  CWERReporter finishing e
vent handling. (00000000)
2014-12-17      00:54:32:942     920    a3c     Report  CWERReporter finishing e
vent handling. (00000000)
2014-12-17      00:54:32:942     920    a3c     Report  CWERReporter finishing e
vent handling. (00000000)
2014-12-17      00:54:32:942     920    a3c     Report  CWERReporter finishing e
vent handling. (00000000)
2014-12-17      00:54:32:942     920    a3c     Report  CWERReporter finishing e
vent handling. (00000000)
2014-12-17      00:54:32:942     920    874     AU      >>##  RESUMED  ## AU: Se
arch for updates [CallId = {544A18F0-EC84-497E-ADEE-F8DEF8F09585}]
2014-12-17      00:54:32:942     920    874     AU        # 49 updates detected
2014-12-17      00:54:32:942     920    874     AU      #########
2014-12-17      00:54:32:942     920    874     AU      ##  END  ##  AU: Search
for updates [CallId = {544A18F0-EC84-497E-ADEE-F8DEF8F09585}]
2014-12-17      00:54:32:942     920    874     AU      #############
2014-12-17      00:54:32:942     920    874     AU      Successfully wrote event
 for AU health state:0
2014-12-17      00:54:32:942     920    874     AU      #############
2014-12-17      00:54:32:942     920    874     AU      ## START ##  AU: Refresh
 featured updates info
-- More (0%) --

At this point you might be better off opening this massive file in wordpad or notepad++ and use its search features. But you get the point. However, sometimes you want to see what is being added to a log file in real time. And that dovetails to...

Monitoring

As I mentioned before, when tracking down issues I like to see what a log file spits out as I do something. I will use here a real example that happened today: let's say you have two Windows servers where serverA runs a service on port, say, 8002 that a program on serverB connects to. And example to this setup would be a web server reaching a database server. Problem is that the two servers are not talking to each other. Since both programs/services are commercial products, you contact both vendors. VendorB states it must be a firewall issue or misconfiguration on serverA. You run netstat on serverA and see that the process is running:

Active Connections

  Proto  Local Address          Foreign Address        State
  TCP    0.0.0.0:135            0.0.0.0:0              LISTENING
  RpcSs
 [svchost.exe]
  TCP    0.0.0.0:445            0.0.0.0:0              LISTENING
 Can not obtain ownership information
  TCP    0.0.0.0:3389           0.0.0.0:0              LISTENING
  TermService
 [svchost.exe]
  TCP    0.0.0.0:5985           0.0.0.0:0              LISTENING
 Can not obtain ownership information
  TCP    0.0.0.0:8002           0.0.0.0:0              LISTENING
 [probltr.exe]
  TCP    0.0.0.0:47001          0.0.0.0:0              LISTENING
 Can not obtain ownership information
  TCP    0.0.0.0:49152          0.0.0.0:0              LISTENING
 [wininit.exe]
  TCP    0.0.0.0:49153          0.0.0.0:0              LISTENING
  EventLog
 [svchost.exe]

Next step you do is connect from a machine which is allowed by the network firewall to reach serverA using telnet or nmap or netcat or even your own crafted Powershell script; pick your poison. It works. Then you do the same from serverA, and get the same results. So, then next step now is to see if vendorB's program is talking to serverA.

We could install wireshark, but then we look at the name of this blog entry and decided to use only what comes with Windows. Since we have network questions, let's make the firewall log on both servers a bit more verbose

PS C:\Windows\system32> netsh firewall set logging droppedpackets = enable connections= enable

IMPORTANT: Command executed successfully.
However, "netsh firewall" is deprecated;
use "netsh advfirewall firewall" instead.
For more information on using "netsh advfirewall firewall" commands
instead of "netsh firewall", see KB article 947709
at http://go.microsoft.com/fwlink/?linkid=121488 .

Ok.

PS C:\Windows\system32>
What we told it to do is to log every time a packet is dropped and a connection is started no matter the outcome. We should be good to go but I would sleep better at night by verifying:
PS C:\Windows\system32> netsh firewall show logging

Log configuration:
-------------------------------------------------------------------
File location   = C:\Windows\system32\LogFiles\Firewall\pfirewall.log
Max file size   = 4096 KB
Dropped packets = Enable
Connections     = Enable

IMPORTANT: Command executed successfully.
However, "netsh firewall" is deprecated;
use "netsh advfirewall firewall" instead.
For more information on using "netsh advfirewall firewall" commands
instead of "netsh firewall", see KB article 947709
at http://go.microsoft.com/fwlink/?linkid=121488 .


PS C:\Windows\system32>
Note that it even told us the path to the firewall log, but we kinda new that from earlier on, right?

So let's do some monitoring, and to do that we need to get some help from Powershell. Now there are many ways to run powershell, but if you are still on the DOS prompt, how about if you just type powershell there? You will know you are in powershell because your prompt is now PS C:\> (note the PS in the front)

C:\>powershell
Windows PowerShell
Copyright (C) 2009 Microsoft Corporation. All rights reserved.

PS C:\> 
As this blog entry is getting long, and because I know the outcome, I will focus only on serverB.

If you want to emulate

tail -f C:\Windows\system32\LogFiles\Firewall\pfirewall.log
in Powershell, you can do something like

Get-Content -Path "C:\Windows\System32\LogFiles\Firewall\pfirewall.log" -wait

Since I only care about the entries that go to serverA whose IP (192.168.1.5) I happen to know, I can emulate

tail -f C:\Windows\system32\LogFiles\Firewall\pfirewall.log | grep '192.168.1.5'
By doing
PS C:\Windows\system32> Get-Content -Path "C:\Windows\System32\LogFiles\Firewall\pfirewall.log" -wait| Select-String -pa
ttern "192.168.1.5"

2015-01-02 07:50:09 ALLOW TCP 192.168.2.7 192.168.1.5 34414 5001 0 - 0 0 0 - - - SEND
2015-01-02 09:54:45 ALLOW TCP 192.168.1.5 192.168.2.7 57842 5000 0 - 0 0 0 - - - RECEIVE
2015-01-02 10:08:09 ALLOW TCP 192.168.2.7 192.168.1.5 38365 5001 0 - 0 0 0 - - - SEND
2015-01-02 10:09:09 ALLOW TCP 192.168.2.7 192.168.1.5 38403 5001 0 - 0 0 0 - - - SEND
2015-01-02 10:10:52 ALLOW TCP 192.168.1.5 192.168.2.7 57973 5000 0 - 0 0 0 - - - RECEIVE
2015-01-02 10:13:09 ALLOW TCP 192.168.2.7 192.168.1.5 38525 5001 0 - 0 0 0 - - - SEND
2015-01-02 10:15:09 ALLOW TCP 192.168.2.7 192.168.1.5 38584 5001 0 - 0 0 0 - - - SEND
2015-01-02 10:16:09 ALLOW TCP 192.168.2.7 192.168.1.5 38613 5001 0 - 0 0 0 - - - SEND
2015-01-02 10:19:09 ALLOW TCP 192.168.2.7 192.168.1.5 38674 5001 0 - 0 0 0 - - - SEND
2015-01-02 10:26:09 ALLOW TCP 192.168.2.7 192.168.1.5 38853 5001 0 - 0 0 0 - - - SEND
2015-01-02 10:28:09 ALLOW TCP 192.168.2.7 192.168.1.5 38919 5001 0 - 0 0 0 - - - SEND
2015-01-02 10:34:09 ALLOW TCP 192.168.2.7 192.168.1.5 39090 5001 0 - 0 0 0 - - - SEND
2015-01-02 10:36:09 ALLOW TCP 192.168.2.7 192.168.1.5 39146 5001 0 - 0 0 0 - - - SEND
2015-01-02 10:46:09 ALLOW TCP 192.168.2.7 192.168.1.5 39497 5001 0 - 0 0 0 - - - SEND
2015-01-02 10:47:12 ALLOW TCP 192.168.2.7 192.168.1.5 39528 5001 0 - 0 0 0 - - - SEND
2015-01-02 10:50:09 ALLOW TCP 192.168.2.7 192.168.1.5 39625 5001 0 - 0 0 0 - - - SEND
2015-01-02 10:52:09 ALLOW TCP 192.168.2.7 192.168.1.5 39701 5001 0 - 0 0 0 - - - SEND
2015-01-02 10:54:09 ALLOW TCP 192.168.2.7 192.168.1.5 39770 5001 0 - 0 0 0 - - - SEND
2015-01-02 11:05:40 ALLOW TCP 192.168.2.7 192.168.1.5 40057 5001 0 - 0 0 0 - - - SEND
2015-01-02 11:08:09 ALLOW TCP 192.168.2.7 192.168.1.5 40145 5001 0 - 0 0 0 - - - SEND
2015-01-02 11:13:09 ALLOW TCP 192.168.2.7 192.168.1.5 40306 5001 0 - 0 0 0 - - - SEND
2015-01-02 11:45:09 ALLOW TCP 192.168.2.7 192.168.1.5 41218 5001 0 - 0 0 0 - - - SEND
2015-01-02 11:51:15 ALLOW TCP 192.168.1.5 192.168.2.7 59024 5000 0 - 0 0 0 - - - RECEIVE
2015-01-02 12:22:09 ALLOW TCP 192.168.2.7 192.168.1.5 42375 8002 0 - 0 0 0 - - - SEND

Note that the only time serverB (192.168.2.7) ever connected today to serverA (192.168.1.5) was when I tried to connect to it, in this case using telnet. So, I sent the above to VendorB, which agreed (admited?) their software was misconfigured, and corrected that.

Once you verify both servers are talking to each other, you could then reset the firewall by typing

netsh firewall set logging droppedpackets = disable connections= disable

Friday, February 01, 2013

Grep-based decisions

So I had an interesting problem today: I want to have a script that will decide what to do based
on whether a file has something or not. Specifically, I am running libvirt with KVM/QEMU and wanted to know if a given vm client was configured with PC passthrough. Now, there are a ton of ways to do that, but I wanted to do it using Bourne or bash and grep. You know, something like

root@vmhost:~# virsh dumpxml vmclient | grep "type='pci' managed='yes'"
    
root@vmhost:~# 

since if it has that pattern, it is passing PCI through. What I need then is to have grep look for that pattern and give me back some kind of return code that tells me if it is there or not.

At first I thought grep -q (quiet), as in

virsh dumpxml vmclient | grep -q "type='pci' managed='yes'" | echo $?

would work (you would need then to fish the return code using $?, which is why I put the echo $?). After all we only care whether it finds it or not. But the thing is that it would return 0 no matter it found the pattern or not. Major bummer.

Now, grep has this -c option that would count how many times it finds the pattern. Which probably leads to if it does not find it, the count should be 0, right? Let's test it out:

root@vmhost1:~# virsh dumpxml vmclient|grep -c "type='pci' managed='no'" 
0
root@vmhost1:~# virsh dumpxml vmclient |grep -c "type='pci' managed='yes'" 
1
root@vmhost1:~#

I think you can see where I am going with this. So, here is a scaled-down version of what I ended up writing:

#!/bin/sh
vmclient=$1
have_pci=$(virsh dumpxml ${vmclient} | grep -c "type='pci' managed='yes'" )

if [ "$have_pci" -eq 0 ]
then
   echo "${vmclient} is PCI passthrough-free. Rejoy!"
   # Do something interesting
else
   echo "${vmclient} has PCI passthrough. Be nice to it."
   # Do something interesting
fi

As you can see it puts our little research to work by detecting if the vm whose name you provide as command line argument ($1) is configured to do PCI passthrough or not. Since this is just a sample skeleton code, it just tells us whether it does or not (the if statement); we could then use that info to do something else. In fact, I am using that test in a larger script I wrote; I did not want to include it here because I wanted to focus on one thing.

I hope this might be useful to someone out there. I probably should talk about the pci passthrough madness, but let's leave that for another episode, shall we?