• 一次linux服务器管理的惨痛教训

    系统用的是fedroa8,机房给装系统的时候,分区按默认方式,用lvm管理。

    后来一次机房给拔了一下电,估计文件系统哪儿出问题
    了,磁盘全部变成只读。然后我想检查一下磁盘,运行了一下fsck,结果检查失败,而文件系统又被卸载掉了,所有命令都用不了。只好让机房给重启一下,然
    后系统就起不来了。怀疑机房重启系统的时候发现系统没反应,多起了几下,导致系统检查硬盘的过程被中断。

    为了保存数据,我只好重新加了块硬盘,把系统装在新硬盘上,挂上旧硬盘,我慢慢恢复数据。

    先是遇到lvm的分区挂载问题,这东西不能像别的分区一样直接挂在。网上查了一下:

    先用vgscan,找到虚拟卷,然后用 vgchange -ay 激活虚拟卷,/dev下就有了虚拟卷设备。  默认是/dev/VolGroup00/LogVol00 /dev/VolGroup00/LogVol01这样的。


    mount  /dev/VolGroup00/LogVol00 /root/vg0 挂载,结果报错:mount: you must specify the filesystem type


    fdisk查看
    了一下,发现虚拟卷识别出来了,但就是分区表被破坏了,系统识别不出分区格式。只好再用fsck修复。不停提示,开始还看,后来烦了,加了个   
    fsck
    -y。好,一路顺利,检查完了。mount上虚拟卷,进入目录,傻眼了,分区下只剩下一个lost found文件夹,别的啥都没了。进到
    lost found下面,ls了一下,等了半天才显示出来结果。原来所有文件都被移到这个文件下了,并且都重命名为以#开头,一串数字结尾的文件,好几
    万文件。欲哭无泪啊。

    无奈间,试着grep了一下,发现还好,有的文件夹名字变了但结构还在。赶忙写了个shell脚本恢复数据。幸运的是,主要数据基本上都恢复了。

    总结了一下教训:

    1。fsck不能乱用。先要把文件系统umount掉,然后检查。最好启动到单用户模式下fsck。

    2。
    不必要的时候不要用lvm。真不知道fedora为什么默认用lvm,为了实验技术?这个鬼东西把硬盘弄成一块,要坏全坏,还影响磁盘io性能。网上看到
    还有把boot文件夹也放到lvm下的,这样系统起不来的时候,你想手动加载一下内核地址,你都不知道内核地址应该怎么表示。

    3。分区和备份太重要了。数据库的datadir要手动指定到放数据的分区下,这样重装系统的时候,数据不会丢失。etc目录下的配置文件要备份,不然系统重装后,重新配置一边也够受的。

     

    平时自己本地用linux,服务器管理经验不多,让老鸟看了笑话。吃一堑长一智,我这也算长了一智。

  • 一个纯java的H.264播放器–Onavia Video Player

    在网上闲逛,遇到一个纯java的H.264播放器,看了它的官方网站上的applet,效果确实不错。

     

    支持以下几种格式:

    • .mp4 standard H.264 file format
    • .mpeg standard H.264 file format
    • .h264 standard H.264 file format
    • .avi generic video file extension

    有以下特征:

     

     

    • High definition video. The Onavia H.264 Java Video
      Player plays the standard resolution and high definition video files
      that conform to the latest H.264 video compression standard.
    • End-user controls. The player has all end-user
      functions including: play, pause, rewind, fast forward, video duration,
      elapsed time, clickable progress bar.
    • Open APIs. Video publishers and web developers can
      customize the entire player (e.g. look & feel, colors, borders,
      window size, video resolution, streaming bandwidth, end-user controls).
      The player is fully customizable, and allows a publisher not only to
      control the end user experience, but also gives flexibility to rapidly
      change the end user experience to keep their website and video viewing
      experience fresh. It also allows a publisher to create different end
      user viewing experiences for different websites or within different
      sections of the same website.
    • Cost-effective delivery of high quality video.
      Enables publishers and web developers to implement H.264 quality video
      into a website without the need to implement costly Flash servers.
    • Can pull a video file from multiple domains/servers
    • Platform independence. It works on PCs, Macs, and all popular browser (Internet Explorer, Mozzilla, Firefox)
    • Device independence. Onavia H.264 Java Video
      Player can be easily ported to a variety of mobile devices and
      environments. The only requirement is that a device supports Java.
    • Automatic Bandwidth detection. The player
      automatically senses the available bandwidth at the end user device and
      adjusts the buffering and streaming to deliver the best possible
      viewing experience.

     

    官方网站:

     

    java在多媒体方面很让人失望,那个JMF框架架构不错,但就是功能太弱。这个播放器的出现,至少说明了java在这方面还是有能力的,只是没发挥出来。

  • struts2的时间格式转换问题

    struts2提供了一个时间标签:

     但这个标签很只能在显示的时候用,但如果我想在输入框里显示时间,让用户直接修改时间,怎么弄?datepicker?选择太麻烦,我想让用户输入,并且
    兼容多种日期格式。还有,如果用时间标签的话,每个地方都需要指定format,如果我想修改一下格式,所有的时间显示都变,怎么弄?

    *  In some situations you may wish to apply a type converter globally.
     *  This can be done by editing the file
     * xwork-conversion.properties in the root of your class path
     * (typically WEB-INF/classes) and providing a
     * property in the form of the class name of the object you wish to convert
     * on the left hand side and the class name of
     * the type converter on the right hand side. For example, providing
     * a type converter for all Point objects would mean
     * adding the following entry:
     *
     * com.acme.Point = com.acme.PointConverter
    

     XWorkConverter,先在classpath root下找xwork-conversion.properties文件,这个文件定义了全局转换。然后每遇到新的类需要转换,便查找是否有特殊的自定义转换配置。特殊自定义转换配置文件的路径是:

    className.replace('.', '/')   "-conversion.properties";
    

     比方com.acme.Point的转换配置就是classpath 下的/com/acme/Point-coversion.properties文件。

    ok,这个问题好解决了。

    我的xwork-coversion.properties文件:

    java.util.Date=cn.jolstar.struts.type.DateTypeConverter
    

      我的DateTypeConverter代码:

    /**
     *
     */
    package cn.jolestar.struts.type;
    
    import java.text.DateFormat;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Map;
    
    import org.apache.log4j.Logger;
    import org.apache.struts2.util.StrutsTypeConverter;
    
    /**
     * @author jolestar
     *
     */
    public class DateTypeConverter extends StrutsTypeConverter {
    
    	private static final Logger log = Logger.getLogger(DateTypeConverter.class);
    	public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
    
    	//暂时只考虑这几种日期格式
    	public static final DateFormat[] ACCEPT_DATE_FORMATS = {
    			new SimpleDateFormat(DEFAULT_DATE_FROMAT),
    			new SimpleDateFormat("yyyy年MM月dd日"),
    			new SimpleDateFormat("yyyy/MM/dd") };
    
    	/**
    	 *
    	 */
    	public DateTypeConverter() {
    	}
    
    	/*
    	 * (non-Javadoc)
    	 *
    	 * @see org.apache.struts2.util.StrutsTypeConverter#convertFromString(java.util.Map,
    	 *      java.lang.String[], java.lang.Class)
    	 */
    	@Override
    	public Object convertFromString(Map context, String[] values, Class toClass) {
    		if (values[0] == null || values[0].trim().equals(""))
    			return null;
    		for (DateFormat format : ACCEPT_DATE_FORMATS) {
    			try {
    				return format.parse(values[0]);
    			} catch (ParseException e) {
    				continue;
    			} catch (RuntimeException e) {
    				continue;
    			}
    		}
    		log.debug("can not format date string:"   values[0]);
    		return null;
    	}
    
    	/*
    	 * (non-Javadoc)
    	 *
    	 * @see org.apache.struts2.util.StrutsTypeConverter#convertToString(java.util.Map,
    	 *      java.lang.Object)
    	 */
    	@Override
    	public String convertToString(Map context, Object o) {
    		if (o instanceof Date) {
    			SimpleDateFormat format = new SimpleDateFormat(
    					DEFAULT_DATE_FORMAT);
    			try {
    				return format.format((Date) o);
    			} catch (RuntimeException e) {
    				return "";
    			}
    		}
    		return "";
    	}
    
    }
    

     

    这样,从字符串转换为日期对象的时候,会尝试上面列出的多种日期格式,但输出的时候,则会统一按照DEFAULT—DATE—FORMAT转换。 需要修改格式,只需要修改DEFAULT—DATE—FORMAT。当然,你也可以把它方在配置文件里,便于修改。

     

    了解了这一点,其实也就 明白了struts的类型转换模式。然后,无论是字符串id到持久化对象的转换,还是自定义的字符串到对象之间的转换,都容易了。

  • Dspace架设经验

    1.Dspace是什么?
          dspace.org
          The DSpace digital repository system captures, stores, indexes, preserves, and distributes digital research material.
          简单一点,Dspace是一个数字图书馆系统,一般用于研究机构储存和发布研究资源.

    2.Dspace的安装:
       windows
        wiki.dspace.org/index.php/DSpaceOnWindows
        linux:
        wiki.dspace.org/index.php/Installing_DSpace_on_Ubuntu_6.06_(LTS)

    3.Dspace架设的一些经验
         我当时使用的版本是dspace3.2
        中文问题
         Dspace会把每个item的标题和作者的首字母截取下来,做为按字母索引.但这对中文就不起作用了.所以我用pinyin4j这个开源项目,把标题和作者转换为拼音,然后截取首字母.
         邮件验证问题
         Dspace中只让用户设置邮件服务器,但并没让设置用户和密码,所以你必须用自己的邮件服务器.这个可以修改一下org.dspace.core.Email类的源码,加入验证.在代码Transport.send(message)处,加入以下代码:

    java 代码

    //jolestar add for mail auth
             String user = ConfigurationManager.getProperty("mail.user");
             String password = ConfigurationManager.getProperty("mail.password");
             Transport transport=session.getTransport("smtp");
             if(user==null||password==null)
             {
                 user = "";
                 password="";
             }
             transport.connect(server,user,password);
             transport.sendMessage(message,message.getAllRecipients());
             transport.close();
    
             //Transport.send(message); 
    

     并将上面那行代码注释了.在配置文件中就可以用mail.user和mail.password配置邮件用户了.不过这个问题在最新版的dspace中已经不存在了.

  • struts2 checkboxlist 的一个问题

    下面是java对象。

    package cn.jolestar.struts;
    
    /**
     * @author jolestar
     *
     */
    public class Language {
    
    	private Long id;
    	private String name;
    
    	/**
    	 *
    	 */
    	public Language() {
    	}
    
    	public Long getId() {
    		return id;
    	}
    
    	public void setId(Long id) {
    		this.id = id;
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	@Override
    	public int hashCode() {
    		final int prime = 31;
    		int result = 1;
    		result = prime * result   ((id == null) ? 0 : id.hashCode());
    		return result;
    	}
    
    	@Override
    	public boolean equals(Object obj) {
    		if (this == obj)
    			return true;
    		if (obj == null)
    			return false;
    		if (getClass() != obj.getClass())
    			return false;
    		final Language other = (Language) obj;
    		if (id == null) {
    			if (other.id != null)
    				return false;
    		} else if (!id.equals(other.id))
    			return false;
    		return true;
    	}
    
    }
    

     

     

     

    package cn.jolestar.struts;
    
    import java.util.List;
    
    /**
     * @author jolestar
     *
     */
    public class Album {
    
    	private Long id;
    	private String name;
    	private List languages;
    	/**
    	 *
    	 */
    	public Album() {
    	}
    	public List getLanguages() {
    		return languages;
    	}
    	public void setLanguages(List languages) {
    		this.languages = languages;
    	}
    
    }
    

     

     下面是jsp标签:

     

     

     

     

    action中有个getLanguages()方法,返回数据库中的所有语言。按道理我编辑Album的时候,checkboxlist中Album的已经拥有的语言会自动选中。但怎么弄,它就是不选中。没办法,看了一下struts2的相关源码,才明白了。

     

    struts2 checkboxlist 的freemarker模板:

     

    ${itemValue?html}
        
    
       
    

     

     if tag.contains(parameters.nameValue,
    itemKey)这个if语句决定该checkbox是否选中。tag.contains()最终调用的是
    org.apache.struts2.util.ContainUtil中的这个方法:

     

    public static boolean contains(Object obj1, Object obj2) {
            if ((obj1 == null) || (obj2 == null)) {
                //log.debug("obj1 or obj2 are null.");
                return false;
            }
    
            if (obj1 instanceof Map) {
                if (((Map) obj1).containsKey(obj2)) {
                    //log.debug("obj1 is a map and contains obj2");
                    return true;
                }
            } else if (obj1 instanceof Collection) {
                if (((Collection) obj1).contains(obj2) || ((Collection) obj1).contains(obj2.toString())) {
                    //log.debug("obj1 is a collection and contains obj2");
                    return true;
                }
            } else if (obj1.getClass().isArray()) {
                for (int i = 0; i < Array.getLength(obj1); i  ) {
                    Object value = null;
                    value = Array.get(obj1, i);
    
                    if (value.equals(obj2)) {
                        //log.debug("obj1 is an array and contains obj2");
                        return true;
                    }
                }
            } else if (obj1.toString().equals(obj2.toString())) {
                //log.debug("obj1 is an object and it's String representation equals obj2's String representation.");
                return true;
            } else if (obj1.equals(obj2)) {
                //log.debug("obj1 is an object and equals obj2");
                return true;
            }
    
            //log.debug("obj1 does not contain obj2: "   obj1   ", "   obj2);
            return false;
        }
    

     

     

    tag.contains(parameters.nameValue,
    itemKey)的参数parameters.nameValue是該标签的值,在这里就是album.languages,
    parameters.list
    是languages,itemKey是循环中的当前language的id。album.languages包含的是Language对象,而
    struts2却在其中查找itemKey–就是Language的id,当然就无法查找到,所以不能自动选中。

     

    我把checkboxlist的模板改了一下。

     

    ${itemValue?html}
    	
    
      &nbsp;
    

     就是将tag.contains(parameters.nameValue,
    itemKey)改成了tag.contains(parameters.nameValue,it),it就是当前循环的Language对象,在
    struts2的iterator 标签里设置

     

    .(注意:如果是最新版的struts2,应该用var 而不是id).

     

    这样就好了。需要注意的是language必须正确overwrite  equals和hashCode方法。

     

  • SUSE10.3的桌面

     

       虽然认识linux也有三年多了,但这三年多里,从windows到linux,不习惯,再换到windows,兴趣来了,再换过来。翻来覆去,折
    腾了好多遍。终于在半年前完全抛弃了windows,转移到linux下来。linux和windows是两种不同的思维方式,思维方式换了,别的就都习
    惯了。最近把我的笔记本的系统升级到suse10.3,贴几张桌面截图。

       我的笔记本是联想F40A,装上suse之后,除了声卡需要特别配置,别的都完全正常使用,包括无线网卡以及蓝牙。因为声卡用了一个微软的啥UAA技术,windows下安装声卡驱动都要先装那个UAA驱动。
    当然,那些鸡肋似的按钮是没办法用了。所以建议打算买本装linux的朋友们优先考虑预装linux的笔记本。

     

     

subscribe via RSS