Main       Comic       Forums       Anime       Tools       Fun       
Categories
Recent Articles
Recent Posts
Buy DSG Items
The DeadGod Anime Manager
helps you stay up-to-date
on your favorite anime series.
Recent Posts       Popular Articles       Popular Threads       [ View All Recent Posts ]
1. DSG Bugged, oh noes! by Darth Druka -- 1H 7M ago.
2. DSG Bugged, oh noes! by DranoK -- 2H 29M ago.
3. DeadGod Survival Game - Cycle 12 by -- 2H 30M ago.
4. DeadGod Survival Game - Cycle 11 by DranoK -- 2H 36M ago.
 
[ Login | Register ]
 
Viewing latest 20 tagged INTERMEDIATE.
Aug
20
Monday, August 20th, 2007 (22741 Views)
Intermediate
DranoK
Most Linux admins are well-versed with crontab. All too often, however, I see people using crontab to schedule a job that's only intended to run once. This not only clutters your cron file but can potentially be dangerous if you forget to un-schedule your job before it runs again.

Luckily there's an alternative: at

Prerequisites:
o Familiarity with the bash shell


The at command simply runs a job once at some specified point in the future. Unlike crontabs, which will only use your user environment if you explicitly tell it to, at will use your environment by default.

The basic invocation patterns of at are:

Listing 1: Basic invocation:
1) at time
2) at time < /file/with/commands
3) echo "some command" |at time

In the first example after pressing enter you will be dropped into the at> shell. Here type the commands, one per line, you would like to be executed.

The second example is non-interactive. Instead of typing your commands into the at> shell, put them into the /file/with/commands file instead. Note that you do not put a shabang (#!/bin/sh) at the top of your script! If you have a script you want to run, do not specify "at time < /path/to/script"--instead create a new text file with one line, "/path/to/script" in it, and use that file as your source to at (at time < /path/to/newfile).

The third example is useful if you want to run a single command at a specified time. For example, "echo /path/to/script |at time"


Permalink - Forum Thread - 9 Comments - Subscribe!Social Bookmark Button



Jul
11
Wednesday, July 11th, 2007 (16067 Views)
Intermediate
DranoK
It can be useful at times to have a shell script behave differently if it's run interactively vs. run from cron or other non-interactive means. For example, you may want the script to send email on certain conditions if it's run from cron, but simply print the message to standard out if it's being run interactively.

Prerequisites:
o Familiarity with the bash shell
o Shell scripting experience

One solution is to wrap the interactive cron with a non-interactive script. This generally isn't the best method as it requires duplicating code in two separate scripts and possibly creating hacked-together ways for the script to interact.

A better solution is to test if the shell is a tty or not.

Listing 1: Test if a shell is a TTY
#!/bin/bash

tty -s
TTYTEST=$?

$? is a special bash variable which means the return code of the most recent command, in this case "tty -s". Unix commands generally return 0 on success, and some number greater than 0 on failure. For "tty -s", a 0 (success) return code means the shell is a TTY, while anything other than 0 means the shell is not. We can now use $TTYTEST to alter the behavior of our script.

Listing 2: Altering script flow based on TTY test
#!/bin/bash

tty -s
TTYTEST=$?

# Random script code here, until we want to do something different based on TTY

if [ $TTYTEST -gt 0 ]; then
  # Code to run if shell is NOT a TTY
else
  # Code to run if the shell IS a TTY
fi

The "-s" option to the tty command tells it to run silently. If you don't specify -s the tty command will print your TTY to standard out if you have one, or "not a tty" if you do not. If you don't want to deal with return codes you can do the following, however personally I think assigning a variable to the return code of "tty -s" is a more elegant way of doing this.

Listing 3: Alternate method to avoid using return codes
#!/bin/bash

TTYTEST=`tty`

# Random script code here, until we want to do something different based on TTY

if [ "$TTYTEST" = 'not a tty' ]; then
  # Code to run if shell is NOT a TTY
else
  # Code to run if the shell IS a TTY
fi

Note that $TTYTEST must be put in quotes since it is a string. The above method can be simplified into a one-line check if you only need to know if the shell is a TTY or not for one if statement.

Listing 4: Quick one-liner to test if a shell is a TTY
#!/bin/bash

if [ "`tty`" = 'not a tty' ]; then
  # Code to run if shell is NOT a TTY
else
  # Code to run if the shell IS a TTY
fi

Just as the $TTYEST variable had to be put in quotes since it was a string, so must `tty` when ran explicitly. Since `tty` will return a string, this must be wrapped in quotes as "`tty`" for it to be used.
Permalink - Forum Thread - 4 Comments - Subscribe!Social Bookmark Button



May
16
Wednesday, May 16th, 2007 (16213 Views)
Intermediate
DranoK
Email is often used as a tool for servers to send reports, notifications and customer correspondence. It can be difficult to troubleshoot the content of messages, however, without resorting to lots of messy code changes or setting up a network of test mailboxes.

This tutorial will show you how to temporarily stop all mail from being sent on a single server so you can inspect the individual mail messages and delete them before they're delivered to an actual person. Any legit mail will not be lost and will be sent once your debugging is complete.

Prerequisites:
o Familiarity with the bash shell
o Familiarity with firewall concepts
o Familiarity with the SMTP protocol
o Basic familiarity with the iptables command

Most web and app servers run a local MTA (Mail Transfer Agent) for system crons and users to send mail with. Frequently this MTA is bound to the localhost interface (127.0.0.1) so external hosts can't access it.

Most applications use their host's local MTA instead of directly opening an outgoing SMTP connection to some random host on port 25. Apps that don't directly use the local MTA are usually configured to use localhost (127.0.0.1) as their mail server so messages aren't lost if there is a network failure.

All mainstream MTAs store mail messages in a queue if they are not able to be immediately sent (if they are disconnected from the network, for example, or if the relay they are trying to send mail to is down). While a mail message is queued it is stored on the file system in plain text.

We have two requirements while trying to debug our app's outgoing mail:

1) We don't want our test messages to reach actual recipients who may be confused by the mail.
2) We want real mail that wasn't part of our test to be delivered normally when we are finished.

Yes, we could mess with the MTA's configuration to try to do this. We could modify the app sending the messages to store them to a file instead.

A much simpler method, however, is to use iptables instead.

Since we want all outgoing messages to be queued we need to prevent the MTA from reaching any external host over port 25 (SMTP). However, since our app may be trying to send mail to localhost (127.0.0.1), we must ensure that port 25 on localhost remains open. To do this we need two iptable rules:

Listing 1:
iptables -A OUTPUT -p tcp -d 127.0.0.1 --dport 25 -j ACCEPT
iptables -A OUTPUT -p tcp  --dport 25 -j REJECT

Most iptables rules are put on the INPUT chain--that is, they manage incoming traffic. In this case we use "-A OUTPUT" because we want to manage outgoing traffic.

The first rule says to ACCEPT all tcp traffic going to localhost (127.0.0.1) on port 25 (SMTP).

The second rule says to REJECT all tcp traffic going to any destination on port 25.

Since the rule to accept localhost traffic is above the rule to deny all outgoing port 25 traffic we are still able to connect to port 25 of localhost. Also note that it is important to use REJECT instead of DROP, since REJECT will cause the MTA's outgoing connection to fail immediatly, while DROP would cause it to hang until it times out.

Running "iptables -L" should now report something similar to the following:

Listing 2:
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             localhost.localdomaintcp dpt:smtp
REJECT     tcp  --  anywhere             anywhere           tcp dpt:smtp reject-with
icmp-port-unreachable

Now all mail being sent will be queued. Your MTA's log file will most likely say the mail has been deferred due to a connection timeout.

Where these messages are stored is entirely dependent on your MTA software and how it was configured. In the case of sendmail, they will likely be in /var/spool/mqueue. Sendmail separates the envelope header from the body. The reasons for this are outside the scope of this article, however it is sufficient to explain that you may need to look at two separate files in order to see an entire email.

Different MTAs use different naming schemes and IDs for these files, however it is generally fairly simple to figure out what each of these files is. Once you find where your MTA stores it's queued messages it shouldn't be difficult to find the debug info you were looking for regardless of how much or little you know about the SMTP protocol and your specific MTA.

Once you have what you need you should delete any files that you don't want sent. Naming schemes vary, but in the case of sendmail all queue files are a string of letters followed by the message ID. It's generally safe to just replace the first 3-5 characters of a file you want to delete in the queue directory with * so you delete all files associated with that message.

For example, if you need to delete a file named "dfj2BIK8802525", use "rm *K8802525" to make sure you delete all associated envelope files. If no legit mail was sent during this time you can safely remove all files in the spool directly.

Remove the iptables rules with "iptables -F" to clear the entire chain. Note that this will remove ALL iptables rules, not just the two you added above. If your had custom iptables rules setup you should either restore them after running "iptables -F" or selectively remove the two rules we added in this tutorial.

The queued mail will now be sent the next time the MTA processes its queue, generally within an hour. Most MTAs have the ability to force processing its queue--using sendmail, for example, you can issue "/usr/sbin/sendmail -q" to force processing of the queue.

See Also:
o IPTables
  http://en.wikipedia.org/wiki/Iptables
o The SMTP Protocol
  http://en.wikipedia.org/wiki/Smtp
o Sendmail
  http://en.wikipedia.org/wiki/Sendmail
o Postfix
  http://en.wikipedia.org/wiki/Postfix_%28software%29


Permalink - Forum Thread - Reply to this - Subscribe!Social Bookmark Button



Mar
22
Thursday, March 22nd, 2007 (15665 Views)
Intermediate
DranoK
Prerequisites:
o Familiarity with the bash shell
o Familiarity with the find command
o Beginner's knowledge of what an inode is

I've often ranted about what I consider to be a lack of competency in the IT field. I blame much of this on the interview process--it's difficult to assess a candidate's skill by simply asking questions. Having a candidate sit down in front of a laptop and try to solve an actual problem instead can be much more useful. Below is one of many lab exercises I use.

Listing 1:
Problem:  You are tasked with removing the following files.
          You must remove each file individually.

Neptune:/tmp/example3 # ls -lrat
total 12
drwxrwxrwt 11 root   root  8192 Mar 22 12:50 ..
-rw-r--r--  1 dranok users    0 Mar 22 12:51 -this-file-starts-with-a-dash
-rw-r--r--  1 dranok users    0 Mar 22 12:51 数独」
-rw-r--r--  1 dranok users    0 Mar 22 12:52         how many spaces
-rw-r--r--  1 dranok users    0 Mar 22 12:52 immutable
drwxr-xr-x  2 dranok users 4096 Mar 22 12:52 .

I say each file must be removed individually because in real-life scenarios you're not going to be able to rm -rf the entire directory. In fact, this is a dangerous idea when you have files with strange characters--you may end up deleting something important. Further, there may be files in the directory you need to keep. Besides, running rm -rf on the folder won't always work.

I like this example because each of these files is increasingly difficult to remove.

Most people try to remove the immutable file first. They get the following error, even as root.

Listing 2:
Neptune:/tmp/example3 # rm immutable
rm: remove write-protected regular empty file `immutable'? y
rm: cannot remove `immutable': Operation not permitted

Nope, this isn't an NFS share. so why can't root delete this file? We'll come back to this one.

The "how many spaces" file (which starts with a number of spaces) is the easiest to remove. Just use a wildcard and this one is simple:

Listing 3:
Neptune:/tmp/example3 # rm *how*
Neptune:/tmp/example3 # ls -lrat
total 12
-rw-r--r--  1 dranok users    0 Mar 22 12:51 -this-file-starts-with-a-dash
-rw-r--r--  1 dranok users    0 Mar 22 12:51 数独」
-rw-r--r--  1 dranok users    0 Mar 22 12:52 immutable
drwxrwxrwt 11 root   root  8192 Mar 22 13:00 ..
drwxr-xr-x  2 dranok users 4096 Mar 22 13:04 .

The next easiest is the "-this-file-starts-with-a-dash" file. Most people tend to struggle with this one.

Listing 4:
Neptune:/tmp/example3 # rm -this-file-starts-with-a-dash
rm: invalid option -- t
Try `rm ./-this-file-starts-with-a-dash' to remove the file
Try `rm --help' for more information.
Neptune:/tmp/example3 # rm *dash
rm: invalid option -- t
Try `rm ./-this-file-starts-with-a-dash' to remove the file
Try `rm --help' for more information.

Even wildcards won't work here. The problem is that rm is interpreting the dash as an argument. The easiest answer is to remember that modern Linux commands use getopt, and that two dashes means "end of options":

Listing 5:
Neptune:/tmp/example3 # rm -- *dash
Neptune:/tmp/example3 # ls -lrat
total 12
-rw-r--r--  1 dranok users    0 Mar 22 12:51 数独」
-rw-r--r--  1 dranok users    0 Mar 22 12:52 immutable
drwxrwxrwt 11 root   root  8192 Mar 22 13:00 ..
drwxr-xr-x  2 dranok users 4096 Mar 22 13:08 .

Next we'll tackle the file that contains kanji (数独」). If your terminal (or web browser) doesn't have the Japanese fonts installed this likely shows up as a series of boxes. How do you selectively remove this file?

The answer is to delete the file via its inode. Among other things, an inode is a unique numerical ID for every file on your filesystem.

To see these inode values, use "ls -li":

Listing 6:
Neptune:/tmp/example3 # ls -li
total 0
2573051 -rw-r--r-- 1 dranok users 0 Mar 22 12:52 immutable
2573049 -rw-r--r-- 1 dranok users 0 Mar 22 12:51 数独」

Now we know the inode is 2573049. To remove it, we invoke the find command:

Listing 7:
Neptune:/tmp/example3 # find . -maxdepth 1 -inum 2573049 -ok rm {} \;
< rm ... ./数独」 > ? y
Neptune:/tmp/example3 # ls -lrat
total 12
-rw-r--r--  1 dranok users    0 Mar 22 12:52 immutable
drwxrwxrwt 12 root   root  8192 Mar 22 13:12 ..
drwxr-xr-x  2 dranok users 4096 Mar 22 13:13 .

Easy enough. We use "-ok" here instead of "-exec" since "-ok" will prompt us before running the command. Removing files with strange characters can be dangerous so it's always a good idea to take precautions. We used "-maxdepth 1" to ensure find wouldn't recurse into subdirectories.

That leaves us with that "immutable" file. At this point, even trying to "rm -rf" the directory will fail:

Listing 8:
Neptune:/tmp # rm -rf example3
rm: cannot remove `example3/immutable': Operation not permitted

The first thing to check when root cannot delete a local (non-NFS) file is the extended filesystem attributes. This can be achieved with the "lsattr" command:

Listing 9:
Neptune:/tmp/example3 # lsattr
----i-------- ./immutable

The "i" in the series of dashes means this file is immutable, or write-protected. To remove this flag from the file you must use the change attribute command, chattr:

Listing 10:
Neptune:/tmp/example3 # chattr -i immutable
Neptune:/tmp/example3 # lsattr
------------- ./immutable
Neptune:/tmp/example3 # rm immutable
Neptune:/tmp/example3 # ls -lrat
total 12
drwxrwxrwt 12 root   root  8192 Mar 22 13:15 ..
drwxr-xr-x  2 dranok users 4096 Mar 22 13:18 .

Congratulations! All the files have been removed.

Extended ext2/ext3 file attributes are very useful, however they are outside the scope of this article. Links are provided at the end of this article for more information.

See Also:
o Removing files with strange characters
  http://www.faqs.org/faqs/unix-faq/fa...section-1.html
  http://www.faqs.org/faqs/unix-faq/fa...section-2.html
o Inodes
  http://en.wikipedia.org/wiki/Inode
o The find command
  http://www.die.net/doc/linux/man/man1/find.1.html
o ext2/ext3 extended file attributes 
  http://www.die.net/doc/linux/man/man1/chattr.1.html


Permalink - Forum Thread - Reply to this - Subscribe!Social Bookmark Button



Dec
27
Wednesday, December 27th, 2006 (16647 Views)
Intermediate
DranoK
One of the frustrations I deal with on nearly a day-to-day basis is people's misconceptions about how memory is allocated under Linux 2.4 and later.

Listing 1: Tools to report memory usage
* top
* free -m
* cat /proc/meminfo

Let's take a typical example. The "free -m" output below is from a production system that has been running for 80 days.

Listing 2:
             total       used       free     shared    buffers     cached
Mem:          3956       3939         16          0         81       3504
-/+ buffers/cache:        353       3602
Swap:        16378          0      16378

This system has 4GB of physical memory and 16GB of swap. At first glance it looks like 99.57% of the memory is in use. Your first instinct would be to run "top", press capital "M" to sort by memory usage and find out what the hell is taking up so much memory. Doing so will yield no results, however--on this particular system top will show no process taking up more than around 100MB of memory. This can be confirmed with the "ps" command.

So where did all this memory go? The answer lies in the theory of memory management. In particular, the Linux memory management system believes in the following two principles:

1) No matter how much memory is in use, system performance will not be impacted until it is required to use swap space.
2) Unused physical memory is wasted.

Now we can tackle the first line of the "free -m" output.

Listing 3:
             total       used       free     shared    buffers     cached
Mem:          3956       3939         16          0         81       3504

The key lies in the last two columns: buffers and cached. The largest of these is cached. Whenever Linux accesses a file on a filesystem it stores the content of that file in memory. As long as the data doesn't change, subsequent requests for that file will be read from memory instead of physical disk. This vastly improves file access time.

Memory used in such a manner can be freed up almost instantly, thus should really be counted as free memory instead of used. The "-/+ buffers/cache" line of our "free -m" output reflects this.

Listing 4:
             total       used       free     shared    buffers     cached
Mem:          3956       3939         16          0         81       3504
-/+ buffers/cache:        353       3602

Actual used memory here is 353MB. Free memory is 3602MB (Don't add the original 16MB back to this--it's already accounted for). That means over 90% of this system's memory is free and available for use. Quite a bit different than only having 16MB of memory free.

The 3602MB value comes from adding the 3504MB of cache with the 81MB of buffers and 16MB of actual free memory. The 353MB of used memory comes from taking total memory and subtracting the "virtually free" 3602MB value. Note that due to rounding these values may be a bit off.
Permalink - Forum Thread - 11 Comments - Subscribe!Social Bookmark Button




Older Articles
 
 
DeadGod.Net - Cute Evil Atheists
Encouraging critical thought and general enjoyment since 2001.
Want to join our community? Have suggestions or comments?
Contact Us or Visit our forums.