Archive

Posts Tagged ‘linux’

虚拟机中Host与Guest文件共享

April 13th, 2010 西坪 1 comment

最近很多工作在Linux下做,但是因为整个公司的环境是Windows,很多事情也经常要在Windows下处理。于是在Windows XP上用VMware搭建了OpenSUSE,同时使用这两种系统。经过这段时间的使用,觉得OpenSUSE的桌面支持确实是做得不错的,似乎比Ubuntu更加方便简单。但是Ubuntu更流行,很多简单的设置问题,网络上随处可见Ubuntu的解决方案,而SUSE的方案却难觅踪影。

例如,我经常使用VMWare的共享文件夹特性来在Host与Guest之间交换数据,共享文件。 但是在OpenSUSE下,却没有找到合适的方法。最终,不得不求助于Samba。 Samba在OpenSUSE上的安装是很方便的,基本上遵照 How To Samba With openSuse 10.3 And Windows XP 的指导,三两步就完成了。 完毕以后,在Windows XP 下映射一个盘符到 \\GUEST_HOSTNAME\users 就完成了。我完全关闭了Guest上的防火墙,有防火墙反而可能招致麻烦。

而在OpenSUSE上访问Windows XP也很简单,基本上遵照 SDB:Access to Windows Shares 的 Manual Procedure 部分,将Windows XP共享目录加入到 /etc/fstab 中:

  1 /dev/sda1            swap                 swap       defaults              0 0
  2 /dev/sda2            /                    ext4       acl,user_xattr        1 1
  3 /dev/sda3            /home                ext4       acl,user_xattr        1 2
  4 proc                 /proc                proc       defaults              0 0
  5 sysfs                /sys                 sysfs      noauto                0 0
  6 debugfs              /sys/kernel/debug    debugfs    noauto                0 0
  7 usbfs                /proc/bus/usb        usbfs      noauto                0 0
  8 devpts               /dev/pts             devpts     mode=0620,gid=5       0 0
  9 //x.x.x.x/work   /mnt/windows    cifs  auto,uid=liuz,gid=users,umask=0002,iocharset=utf8,credentials=/etc/winpasswd 0 0

别忘了保护你的密码文件:

chmod 600 /etc/winpassword

特殊之处,是指定了一个 uid=liuz, 将文件的所有者指定为liuz这个用户,方便增删改等操作。有关 uid,gid,umask等的解释如下: (来源)

uid与gid
uid即user identifer,gid即group identifer。设置所有文件的所有者和群组。gid=64,即权限为所有者可读、写,不能执行,群组用户可读、不能写、执行。
umask
umask即user mask,即用户屏蔽。umask=007,即所有文件的权限中,屏蔽其它使用者的读、写、执行权限。

总结

总结一下我使用的这三种方法:

  • 1) 使用VMware提供的共享文件夹功能。
  • 2) 使用Samba为Windows Host OS 共享Linux Guest OS文件系统。
  • 3) 在Linux Guest OS中mount Host OS (Windows系统)的共享文件夹。
Categories: server & system Tags: , ,

文件锁与进程互斥

January 8th, 2010 西坪 3 comments

有的情况下需要在进程之间实现互斥,这对于普通Java程序来说,因为是运行在虚拟机里的原因,手段远不如原生程序方便,但是也有一些简单的方法可以做到。第一个就是使用Socket监听某个端口,第二种方法是使用文件锁定。

使用Socket实现进程互斥

因为Java服务器套接字都是基于系统的socket接口实现的,而socket接口会保证一个套接字端点在整个系统中是唯一的,所以只需要在应用启动时监听一个端口,就可以让系统不同时启动。虽然方法比较土,但是也能用。

try {
	ServerSocket ss = new ServerSocket(3030);
}catch (Exception e) {
	logger.error("Cannot start", e.printStackTrace());
	System.exit();
}

使用文件锁在进程间同步

另一个实现Java进程间互斥的方法,就是文件锁。不过与上面使用套接字不同,使用文件锁还可以实现更高级的互斥/协作。完全可以用文件锁来实现不同Java进程之间的同步,基本思路与在线程之间使用读写锁同步相似。

JDK本身直接支持文件锁,在FileChannel下有几个与文件锁有关的方法,可以打开一个FileLock对象。当调用FileLock#release()方法,或者Channel关闭,或者JVM退出时都会释放该锁。文件锁是JVM全局的,与Java内部的锁/线程等无关,是进程之间的竞争关系。如果你不想发生意外你的程序挂起,那就应该用FileChannel#trylock,而不是直接使用FileChannel#lock(),这样在不能加锁时可以休眠一段时间再等等,或者超时退出。

文件锁像读写锁一样,可以是加共享锁,也可以加独占锁,还可以给锁定限制范围。这是操作系统本身提供的功能,JDK在操作系统层面上做了封装。在Linux下,其实就是调用fcntl来设置相关的状态。如下面的代码,会给文件加独占锁,如果再起新的进程,进程就会打开文件失败退出。

     char* lockfile;
      int lockfd;
      struct flock lock;
      time_t t;   
 
      if ((lockfd = open(lockfile, O_RDWR)) == -1) {
          fprintf(stdout, "open file %s fail: %s \n", lockfile, strerror(errno));
          exit(1);
      }
 
      t = time(NULL);
 
      lock.l_type = F_WRLCK;
      lock.l_start = 0;
      lock.l_len = 0;
      lock.l_whence = SEEK_SET;
      if (fcntl(lockfd, F_SETLKW, &lock) == -1) {
          fprintf(stdout, "lock file %s fail: %s \n", lockfile, strerror(errno));
      }
      fprintf(stdout, "lock file %s success(%d): %ld \n", lockfile, (int)getpid(), time(NULL)-t);
      sleep(30);
Categories: $Programming Tags: , , ,

Linux Command & Shell Tips (1)

March 22nd, 2009 西坪 No comments

此文用于记录使用 Linux 过程中的与 shell 和 commands 有关的有意思的小知识。

1. The problem of ftp url:
在写一个自动备份的脚本时发现,如果 username 中有 @ 符号时,使用 curl ftp://username:password@host/file 是不行的。这可能是 ftp url 地址格式的一个瑕疵。具体参考 Google Group上的一个讨论 (对于该讨论的正确性本人没有特别考证, 根据作者的观点,在整个URL中出现 “:”、”/”、”@” 都是不可行的。如果您发现此论断有问题请留言)。 还好 curl 可以使用 -n 指定使用 ~/.netrc 中的登录标识。

2. 直接使用 sed 命令批量替换文件中的内容

sed -i 's/\/var\/svn/d:\/data\/svn/g' `grep /var/svn -rl ./*/conf/trac.ini`

sed 命令还有很多用法,可惜平时用得不多,经常忘记了要查资料。

3. 使用 find 命令批量操作 Trac 项目同步SVN

find -maxdepth 1 -mindepth 1  -type d -print -exec trac-admin {} resync \;

对仅仅处理当前目录下的子目录的限定方法比较笨,也许有更好的方法。

find命令是最难用的,再提供一个统计代码行总数的例子。

$ find stat5.1projects/ ! -path '*.common/*' -a ! -path '*bin*' -a ! -path '*st
at.statuser*' -a \( -name *.java -or -name *.sql -or -name *.xml \) | xargs wc
-l
</pre lang="bash">
然后直接通过Shell计算出平均每天的代码行:
<pre lang="bash">
echo $((8888/22))

4. tar error message.

Removing leading `/’ from member names

It’s really annoying when it present in a crontab script. That is why (refer from here):

what do you want suggestions about? tar archives don’t contain absolute paths, only relative ones. this is correct behaviour, as the alternative is really nasty and illogical. this is the same way that other compression programs like winzip work. when you untar somethign you provide an destination directory, which implicity is ‘/’ in your case… but it should be explicit for logical operation

The resolution is using relative path. e.g.

cd /var/www
tar -cf /home/user/backup/wp-backup.tar web
# NOT below
# cd /home/user/backup
# tar -cf wp-backup.tar /var/www/web

5. svn: Delete unversioned files

svn status --no-ignore | grep '^[I?]' | sed 's/^[I?]//' | xargs rm -rf

Here are more frequent ask questions on subversion.

6. 防火墙后面的git通过代理访问:
设置GIT_PROXY_COMMAND系统变量即可。具体参考:Using Git with a SOCKS proxy

7. Ubuntu添加sudo用户:
Edit file /etc/sudoers, add line:

bob  ALL=(ALL) ALL

参考:http://www.linuxhomenetworking.com/wiki/index.php/Quick_HOWTO_:_Ch09_:_Linux_Users_and_Sudo

8. Unix timestamp 与 readable date 之间的转换:
shell:

date -d @1232144092 #timestamp to date
datedate=’1970-01-01 1000000000 sec GMT’
date -d today +%s #date to stamp

Perl:

date -d today +%s | perl -e 'print localtime(<>)."\n"' # to readable time

gawk:

date -d today +%s | gawk 'END{print strftime("%c",$1)}' # to readable time

9. AWK调用shell命令做一些计算

cat $f | awk '! /^NAI/ {cmd="date +%k%M -d @"$3; cmd | getline d; close(cmd); if (d>2357)print d}'

多行时可循环读取:

cmd_= ("cat "naiIdMappingFile);
while (cmd_ | getline d ) {
        split(d, naiIds," ");
        naiIdMaps[naiIds[1]" "]=naiIds[2];
}
close(cmd_)

其中要提醒一下的是,一定要记得 close() 的调用,不然很快会耗光文件描述符。

10. Perl 跟bash脚本配合,逐行对文件执行某些操作:

cat $f | perl -ane '$F[1] =~ s/\D+(\d+)\D+(\d+)\D+(\d+)/$1 $2/g; @cols = split(" ",$F[1]); $F[2] =~ s/\D+(\d+)\D+(\d+)\D+(\d+)/$3/g;print " @F ". scalar($F[2]-$cols[1]) ." \n";';
Categories: Tools & Tips Tags: ,