All posts by Pistolfly

Software Engineer in Tokyo, Japan

Adjust timing of fsck using tune2fs

I rebooted my server but fsck started forcibly on boot and it took long time until the system started.
To show or adjust fsck timing on ext2/ext3/ext4 filesystem, you can use tune2fs.

Show

# tune2fs -l /dev/sda1
・・・(omitted)
Mount count:              7
Maximum mount count:      27
Last checked:             Fri Oct 21 03:41:32 2011
Check interval:           15552000 (6 months)
Next check after:         Wed Apr 18 03:41:32 2012
・・・(omitted)

Stop forcible fsck

# tune2fs -c 0 -i 0 /dev/sda1 
tune2fs 1.39 (29-May-2006)
Setting maximal mount count to -1
Setting interval between checks to 0 seconds

Confirmation

# tune2fs -l /dev/sda1
・・・(omitted)
Mount count:              7
Maximum mount count:      -1
Last checked:             Fri Oct 21 03:41:32 2011
Check interval:           0 (<none>)
・・・(omitted)

Source: tune2fs でfsckを制御 - ike-daiの日記

Prevent an error mail from being sent to the original sender in the case of forwarding failure on Postfix

On Postfix, in the case of forwarding by aliases or .forward, if the forwarding results in an error, the error mail is sent to the original sender. The most easy way to prevent this behavior is setting the alias to a redirection to sendmail command and changing envelope sender address using sendmail -f option like below.

| /usr/sbin/sendmail -f <envelope sender address> <recipient address to forward>

Example:

/etc/aliases

foo: foo, "| /usr/sbin/sendmail -f bar xxx@example.com"

sendmail -f option sets the envelope sender address. This is the address where delivery problems are sent to ("bar" in the above example). This means that an error mail is not delivered to the original sender.

Be careful not to create infinite loop
In the above example, you should be careful that foo does not come to be the last recipient.

[postfix-jp:01469] Re: [Q] .forward で転送失敗のメールを送信者に知らせたくない

Find real type of typedef such as system data types

The easiest way is to use ptype with gdb.

Example:

foo.c

#include <sys/types.h>
struct st { int i; char c; };
typedef int Array[10];
typedef struct st St;
int main(void)
{ 
  size_t s1;
  ssize_t s2;
  pid_t pid;
  Array arr;
  St st1;
  return 0;
}
$ gcc -Wall -g -o foo foo.c
$ gdb foo
(gdb) b main
(gdb) run
(gdb) ptype s1
type = long unsigned int
(gdb) ptype size_t
type = long unsigned int
(gdb) ptype s2
type = long int
(gdb) ptype ssize_t 
type = long int
(gdb) ptype pid
type = int
(gdb) ptype pid_t
type = int
(gdb) ptype arr
type = int [10]
(gdb) ptype Array 
type = int [10]
(gdb) ptype st1
type = struct st {
    int i;
    char c;
}
(gdb) ptype St
type = struct st {
    int i;
    char c;
}

Like the above example,

ptype <expression or type name>

shows real type.

If the type is an array, it also shows its size. If the type is a struct, it also shows the type of the members of the struct. It's convenient.

You can probably find the real type using gcc -E option and looking into preprecessor's output like below, but it's bothersome and possibly needs hard work.

$ gcc -E foo.c | grep ssize_t
typedef long int __ssize_t;
typedef __ssize_t ssize_t;
(ommitted below)

In the above example (x86_64 GNU/Linux), you can find that ssize_t is
__ssize_t => long int

$ gcc -E foo.c | grep ssize_t
typedef long __darwin_ssize_t;
(ommitted)
typedef __darwin_ssize_t ssize_t;
(ommitted)

In the above example (Mac OS X), you can find that ssize_t is
ssize_t => __darwin_ssize_t => long

Setting timeout for open-uri

require 'open-uri'
require 'resolv-replace'
require 'timeout'
TIMEOUT = 3
begin
  timeout(TIMEOUT) do
    open(url) do |f|
      # Do something
    end
  end
rescue TimeoutError => e
  # Do something on timeout
rescue => e
  # Do something on other errors
end
  • Interrupt with timeout is implemented by Ruby's Thread and it is not effective againt the process implemented by C, so DNS name resolution cannot be timeout. resolv-replace overwrites the methods to use Ruby's resolve library for DNS name resolution and enables timeout.
  • TimeoutError is not subclass of StandardError, so you have to catch TimeoutError explicitly.

Source: open-uriにtimeoutを設定する方法 | やむにやまれず

Show differences between remote branch and local branch

First, get remote branches up-to-date.

$ git fetch
$ git svn fetch  # only if you have Subversion remote repository using git-svn

Show remote branches.

$ git branch -a
* master
  remotes/origin/master
  remotes/svn/tags/RELEASE_20101022
  remotes/svn/tags/RELEASE_20101025
  remotes/svn/trunk

Show changes between current local branch and remote branch.

$ git diff remotes/origin/master

Show changes between current local branch and remote branch. (simple)

$ git diff --name-status remotes/origin/master

Show changes between current local branch and remote branch. (simple, Subversion repository)

$ git diff --name-status remotes/svn/trunk

Source: git svn status - showing changes that are not committed to svn - Stack Overflow

Redmine error when synchronizing repositories with Git

I executed Repository.fetch_changesets using script/runner by cron to synchronize repositories of Redline with Git and I got an error below.

git: not found

I modified redmine/lib/redmine/scm/adapters/git_adapter.rb like below and it became OK.

#GIT_BIN = "git"
GIT_BIN = "/usr/local/bin/git"
※ On r4795, r4797, you can set scm_git_command to the path to Git in configuration.yml, so you no longer need such modification like above.

I also encountered an onother problem.
When the user who executes Redmine does not have permission for the Git repository directory (like xxx.git), Redmine shows "The entry or revision was not found in the repository." error on repository page.

Workaround is:

$ sudo chmod o+rx xxxx.git
  • If the repository is in a user's home directory (e.g. on gitosis or gitolite), you also have to do chmod o+x for the user's home directory.

Appending request headers to a request forwarded by mod_rewrite

Set an environment variable using env flag in RewriteRule and use it in RequestHeader append.

  RewriteEngine on
  RewriteRule ^/(.*)$ http://appserver/$1 [P,L,QSA,env=ORG_REMOTE_ADDR:%{REMOTE_ADDR}]
  ProxyPassReverse / http://appserver/
  RequestHeader append X_ORG_REMOTE_ADDR %{ORG_REMOTE_ADDR}e env=ORG_REMOTE_ADDR
  RequestHeader append X-Forwarded-Proto https

mod_rewrite - Apache HTTP Server
たまねぎプログラマハマリ日記:Apache内のCGI環境変数をTomcatに渡す。 - livedoor Blog(ブログ)

Delete or grep the results of find

-exec command {} \;
  • Execute command after find. To pass results of find use {}.
  • You must put a blank before "\;". If a blank is missing, an error occurrs like below.
    $ find . -name *~ -exec rm {}\;
    find: missing argument to `-exec'
    
    $ find . -name *~ -exec rm {}\;
    find: -exec: no terminating ";" or "+"
    
  • To execute more than one command, specify multiple -exec.

Example:

find ~ -name '*bak' -exec rm {} \;
  • In above example, "rm {} \;" following "-exec" is the command to execute. Last ";" denotes the end of the parameters. "\" before ";" is needed to escape "\" so that shell does not evaluate ";".

Example:

Delete all files whose name are *~ (Emacs backup file) in home directory.

$ find ~/ -name "*~" -exec rm {} \;

Delete all .svn directories from working directory tree of Subversion.

find . -name .svn -exec rm -rf {} \;

Grep files in directory tree.
(grep option -H for printing filename headers, -n for printing line number)

find <directory> -type f -exec grep -nH <pattern> {} \;

You can't specify target table 'xxx' for update in FROM clause

On MySQL, you cannot use the same table for both the subquery FROM clause and the update target.

Source: MySQL :: MySQL 5.1 Reference Manual :: 13.2.9.9 Subquery Errors

Example:

mysql> delete from user \
    -> where user.id in \
    -> (select user.id from user \
    -> left join reserve_data on user.id = reserve_data.user_id where reserve_data.id is null);
ERROR 1093 (HY000): You can't specify target table 'user' for update in FROM clause

Workaround

mysql> delete from user \
    -> where user.id in \
    -> (select x.id from \
    -> (select user.id from user left join reserve_data on user.id = reserve_data.user_id where reserve_data.id is null) \
    -> as x \
    -> );
Query OK, 350 rows affected (0.00 sec)

In the above example, the subquery creates an implicit temporary table, so it doesn't count as the same table you're updating.

Source: SQL Delete: can't specify target table for update in FROM clause - Stack Overflow