binfalse
Sync the clock w/o NTP
January 11th, 2013The network time protocol (NTP) is a really smart and useful protocol to synchronize the time of your systems, but even if we are in two-thousand-whatever there are reasons why you need to seek for alternatives...
You may now have some kind of »what the [cussword of your choice]« in mind, but I have just been in an ugly situation. All UDP traffic is dropped and I don't have permissions to adjust the firewall.. And you might have heard about the consequences of time differences between servers. Long story short, there is a good solution to sync the time via TCP, using the Time Protocol and a tool called `rdate` .
Time Master
First off all you need another server having a correct time (e.g. NTP sync'ed), which can be reached at port 37. Let's call this server `$MASTER` . To enable the Time Protocol on `$MASTER` you have to enable the time service in (x)inetd. For instance to enable the TCP service for a current `xinetd` you could create a file in `/etc/xinetd.d/time` with the following contents:
service time
{
disable = no
type = INTERNAL
id = time-stream
socket_type = stream
protocol = tcp
user = root
wait = no
}
Such a file may already exist, so you just have to change the value of the `disable` -key to `no` . Still using inetd? I'm sure you'll find your way to enable the time server on your system :)
Time Slave
On the client, which is not allowed to use NTP (wtfh!?), you need to install `rdate` :
aptitude install rdate
Just call the following command to synchronize the time of the client with `$MASTER` :
rdate $MASTER
Since `rdate` immediately corrects the time of your system you need to be root to run this command.
Finally, to readjust the time periodically you might want to install a cronjob. Beeing root call `crontab -e` to edit root's crontab and append a line like the following:
# m h dom mon dow command
0 */6 * * * [ -x /usr/bin/rdate ] && /usr/bin/rdate $MASTER >> /dev/null
This will synchronize the time of your client with the time of `$MASTER` every six hours. (Don't forget to substitute `$MASTER` using your desired server IP or DNS.)
Notes
Last but not least I want you to be aware that this workaround just keeps the difference in time between both systems less than 0.5 secs. Beyond all doubt, looking at NTP that's very poor. Nevertheless, 0.5 secs delay is much better than several minutes or even hours!
If it is also not permitted to speak to port 37 you need to tunnel your connections or you have to tell the time server to listen to another, more common port (e.g. 80, 443, or 993), as long as they are not already allocated by other services..
Bash Wildcards
September 17th, 2012I wanted to publish this summary about wildcards in the bash (and similar shells) some time ago, but didn’t finish it. But finally it gets published.
The shell handles words or patterns containing a wildcard as a template. Available filenames are tested to see if they fit this template. This evaluation is also called globbing. Let’s have a look at a small example:
me@kile /tmp/blog $ ls
aaa aaa2 aaaa1 aaaa3 aaaa5 abbb bbbb
aaa1 aaa3 aaaa2 aaaa4 aaab acdc caab
me@kile /tmp/blog $ ls *b
aaab abbb bbbb caab
In this example *
is replaced by appropriate characters, and the list of matching files are passed to the ls
command. This set of files will be used in the following examples.
Encode for a single character: `?`
The question mark can be replaced by a single character. So if you want to get the files aaa1
, aaa2
, aaa3
and aaab
you can use the following pattern:
me@kile /tmp/blog $ ls aaa?
aaa1 aaa2 aaa3 aaab
So you see, the ?
is replaced by exactly one character. That is, both aaa
and aaaa1
won’t match.
Encode for a an arbitrary number of characters: `*`
To match any number of characters you can use the asterix *
. It can replace 0
to n
characters, n
is limited by the max length of the file name and depends on the file system you’re using. Adapting the previous snippet you’ll now also get aaa
and aaaa1
:
me@kile /tmp/blog $ ls aaa*
aaa aaa1 aaa2 aaa3 aaaa1 aaaa2 aaaa3 aaaa4 aaaa5 aaab
Encode for a set of characters: `[...]`
Most of the common tasks can be done with the previous templates, but there are cases when you need to define the characters that should be replaced. You can specify this set of characters using brackets, e.g. [3421]
can be replaced by 3
, 4
, 2
or 1
and is the same as [1-4]
:
me@kile /tmp/blog $ ls aaaa?
aaaa1 aaaa2 aaaa3 aaaa4 aaaa5
me@kile /tmp/blog $ ls aaaa[3421]
aaaa1 aaaa2 aaaa3 aaaa4
me@kile /tmp/blog $ ls aaaa[1-4]
aaaa1 aaaa2 aaaa3 aaaa4
As you can see aaaa5 doesn’t match [3421]
, and btw. the order of the specified characters doesn’t matter. And because it would be very annoying if you want to match against any alphabetic character (you would need to type all 26 characters), you can specify character ranges using a hyphen ( a-z
). Here are some exmaples:
Template | Character set |
---|---|
`[xyz1]` | `x` , `y` , `z` or `1` |
`[C-Fc-f]` | `C` , `D` , `E` , `F` , `c` , `d` , `e` or `f` |
`[a-z0-9]` | Any small character or digit |
`[^b-d]` | Any character except `b` , `c` , `d` |
`[Yy][Ee][Ss]` | Case-insensitive matching of yes |
`[[:alnum:]]` | Alphanumeric characters, same as `A-Za-z0-9` |
`[[:alpha:]]` | Alphabetic characters, same as `A-Za-z` |
`[[:digit:]]` | Digits, same as `0-9` |
`[[:lower:]]` | Lowercase alphabetic characters, same as `a-z` |
`[[:upper:]]` | Uowercase alphabetic characters, same as `A-Z` |
`[[:space:]]` | Whitespace characters (space, tab etc.) |
Btw. the files that match such a template are sorted before they are passed to the command.
Validating XML files
September 12th, 2012In the scope of different projects I often have to validate XML files. Here is my solution to verify XML files using a schema.
First of all to validate XML files in Java you need create a SchemaFactory
of the W3C XML schema language and you have to compile the schema (let’s assume it’s located in /path/to/schema.xsd
):
SchemaFactory factory = SchemaFactory.newInstance ("http://www.w3.org/2001/XMLSchema");
Schema schema = factory.newSchema (new File ("/path/to/schema.xsd"));
Now you’re able to create a validator from the schema.
Validator validator = schema.newValidator ();
In order to validate a XML file you have to read it (let’s assume it’s located in /path/to/file.xml
):
Source source = new StreamSource (new File ("/path/to/file.xml"));
Last but not least you can validate the file:
try
{
validator.validate (source);
System.out.println ("file is valid");
}
catch (SAXException e)
{
System.out.println ("file is invalid:");
System.out.println (e.getMessage ());
}
HowTo Debug Bash Scripts
September 8th, 2012Even shell scripts may get very complex, so it is helpful to know how to debug them.
Lets explain it on a small example:
#/bin/bash
echo lets go
# some comment
DIR=/boot
/bin/ls -l $DIR | /bin/grep initrd | wc -l
echo done
Executing it you’ll get an output like this:
usr@srv /tmp % bash test.sh
lets go
112
done
To debug the execution of scripts the bash provides a debugging mode. There is one option -x
to trace the execution
usr@srv /tmp % bash -x test.sh
+ echo lets go
lets go
+ DIR=/boot
+ wc -l
+ /bin/grep initrd
+ /bin/ls -l /boot
112
+ echo done
done
So you see, every line that is executed at the runtime will be printed with a leading +
, comments are ignored. There is another option -v
to enable verbose mode. In this mode each line that is read by the bash will be printed before it is executed:
usr@srv /tmp % bash -v test.sh
#/bin/bash
echo lets go
lets go
# some comment
DIR=/boot
/bin/ls -l $DIR | /bin/grep initrd | wc -l
112
echo done
done
Of course you can combine both modes, so the script is sequentially printed and the commands are traced:
usr@srv /tmp % bash -vx test.sh
#/bin/bash
echo lets go
+ echo lets go
lets go
# some comment
DIR=/boot
+ DIR=/boot
/bin/ls -l $DIR | /bin/grep initrd | wc -l
+ /bin/ls -l /boot
+ wc -l
+ /bin/grep initrd
112
echo done
+ echo done
done
These modes will help you to find some errors.
To modify the output of the tracing mode you may configure the PS4
:
export 'PS4=+${BASH_SOURCE}:${LINENO}:${FUNCNAME[0]}: '
This will also print the file name of the executing script, the line number of the current command that is executed and the respective function name:
usr@srv /tmp % export 'PS4=+${BASH_SOURCE}:${LINENO}:${FUNCNAME[0]}: '
usr@srv /tmp % bash -x test.sh
+test.sh:3:: echo lets go
lets go
+test.sh:6:: DIR=/boot
+test.sh:7:: /bin/ls -l /boot
+test.sh:7:: /bin/grep initrd
+test.sh:7:: wc -l
112
+test.sh:9:: echo done
done
if You don’t want to trace a whole script you can enable/disable tracing from within a script:
# [...]
echo no tracing
set -x
echo trace me
set +x
echo no tracing
# [...]
This will result in something like:
usr@srv /tmp % bash test.sh
[...]
no tracing
+test.sh:14:: echo trace me
trace me
+test.sh:15:: set +x
no tracing
[...]
It is of course also possible to enable/disable verbose mode inside the script with set -v
and set +v
, respectively.
Absolute Path of a Servlet Installation
September 7th, 2012I’m currently developing some Java Servlets and one of the tasks is to create images dynamically. But where to store them accessible for users?
If you want to show the user for example a graph of some stuff that changes frequently you need to generate the image dynamically. The rendering of the graphic is one thing, but where to store the picture so that the visitor can access it from the web?
There were many options to try, and I found that getServletContext().getRealPath (".")
from ServletRequest
› was the result I’ve been looking for. So to spare you the tests I’ll provide the different options (download):
Let’s assume your webapps-directory is /var/lib/tomcat6/webapps/
, your servlet context is project
and the user asks for the servlet test
the output probably looks like:
new File (".").getAbsolutePath () => /var/lib/tomcat6/.
request.getPathInfo () => null
request.getPathTranslated () => null
request.getContextPath () => /project
request.getRealPath (request.getServletPath ()) => /var/lib/tomcat6/webapps/project/test
request.getServletPath () => /test
getServletContext ().getContextPath () => /project
getServletContext ().getRealPath (".") => /var/lib/tomcat6/webapps/project/.
That’s it for the moment ;-)