Winse Blog

走走停停都是风景, 熙熙攘攘都向最好, 忙忙碌碌都为明朝, 何畏之.

使用 Eclipse 远程调试 Java 应用程序

普通Java程序:

1、导出包括调试信息的jar工程

在eclipse中,选择Window > Preferences > Java > Compiler来修改设置。 全选Classfile Generation选项卡内的选项(这里的选项是为了能把Debug需要的信息也写入到class字节码文件[d1])。然后从eclipse导出工程为remoting-debug.jar。

2、服务器运行

1
java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=8000 -jar remoting-debug.jar

3、本地调试

运行后,选择 Run>Debug Configurations…>Remote Java Application 运行就可以远程调试了。

  • Project选项卡选择需要调试的project。(其实只要选择其中一个你要调试的的project即可)
  • Connection TypeStandard (Socket Listen)
  • Port为address的值8000

Tomcat应用:

1、在startup.bat的”:end”前增加

1
2
3
4
5
set JPDA_TRANSPORT=dt_socket
set JPDA_ADDRESS=8000
set JPDA_SUSPEND=y

call "%EXECUTABLE%" jpda start %CMD_LINE_ARGS%

以上设置的这些参数最终在catalina.bat中被调用!

2、参考【java程序】的[步骤3]的操作。 在eclipse里面的设置和上面的java相同。

调试的时刻源码行号对不上

Eclipse下Debug时弹出错误“Unable to install breakpoint due to missing line number attributes,Modify compiler options togenerate line number attributes”

遇到这个错误时找到的解答方案汇总:

  1. 使用Ant编译时,未打开debug开关,在写javac 任务时确认debug=true,否则不能调试。THe settings for the eclipse compiler don’t affect the ant build and even if you launch the ant build from within eclipse. ant controls it’s own compiler settings.you can tell ant to generate debugging info like this ‘javac … debug=“true”…/>(我的问题是因为这个原因);

  2. 编译器的设置问题,window->preferences->java->Compiler在compiler起始页,classfile Generation区域中确认已经勾选了All line number attributes to generated class files。如果已经勾选,从新来一下再Apply一下。或者从项目层次进行设定,项目属性->java compiler同样在起始页,确定已经勾选

Eclipse报的这个错,无非就这两个原因造成的

参考:


【原文地址】

–END

Hadoop上建索引index的程序

源码

\hadoop-1.0.0\src\contrib\index

主要涉及的类

  • org.apache.hadoop.contrib.index.main.UpdateIndex
  • org.apache.hadoop.contrib.index.mapred.IndexUpdater
  • org.apache.hadoop.contrib.index.mapred.IndexUpdateMapper
  • org.apache.hadoop.contrib.index.mapred.IndexUpdatePartitioner
  • org.apache.hadoop.contrib.index.mapred.IndexUpdateCombiner
  • org.apache.hadoop.contrib.index.mapred.IndexUpdateReducer
  • org.apache.hadoop.contrib.index.example.LineDocInputFormat
  • org.apache.hadoop.contrib.index.mapred.IndexUpdateOutputFormat
  • org.apache.hadoop.contrib.index.mapred.IndexUpdateConfiguration

解析

1、UpdateIndex类(main实现读取控制台参数)

UpdateIndex是整个程序的入口,提供参数给用户配置。

  • -inputPaths  –>mapred.input.dir  (V)
  • -outputPath –>mapred.output.dir  (V)
  • -shards –>最终每个reduct建立的索引存放hdfs位置 (V)
  • -indexPath –>sea.index.path
  • -numShards –>sea.num.shards
  • -numMapTasks –>mapred.map.tasks  (V)
  • -conf 添加Configuration xml文件形式的配置方式

shards  通过转换最终保存到Configuration的sea.index.shards

shards参数 与 indexPath和numShards参数 设置一种就可以了。如果没有设置shards,则在main方法中会通过indexPath和numShards生成得到 shards 参数。

从Configuration中获得Updater类: IndexUpdateConfiguration.getIndexUpdaterClass()

1
2
3
4
  public Class<? extends IIndexUpdater> getIndexUpdaterClass() {
    return conf.getClass("sea.index.updater", IndexUpdater.class,
        IIndexUpdater.class);
  }

在UpdateIndex最终调用IndexUpdater

1
updater.run(conf, inputPaths, outputPath, numMapTasks, shards);

2、IndexUpdater类(配置MapReduce Job)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
  public void run(Configuration conf, Path[] inputPaths, Path outputPath,
      int numMapTasks, Shard[] shards) throws IOException {
    JobConf jobConf =
        createJob(conf, inputPaths, outputPath, numMapTasks, shards);
    JobClient.runJob(jobConf);
  }
...
...
  JobConf createJob(Configuration conf, Path[] inputPaths, Path outputPath,
      int numMapTasks, Shard[] shards) throws IOException {
    setShardGeneration(conf, shards);

    // iconf.set sets properties in conf
    IndexUpdateConfiguration iconf = new IndexUpdateConfiguration(conf);
    Shard.setIndexShards(iconf, shards);

    // MapTask.MapOutputBuffer uses "io.sort.mb" to decide its max buffer size
    // (max buffer size = 1/2 * "io.sort.mb").
    // Here we half-en "io.sort.mb" because we use the other half memory to
    // build an intermediate form/index in Combiner.
    iconf.setIOSortMB(iconf.getIOSortMB() / 2);

setShardGeneration(conf, shards);方法从shard path路径获得segment_N来获得generation,并更新shard实例的gen属性。

Shard.setIndexShards(iconf, shards);则是序列化shards为String写入到Configuration中。

接下来的代码,就是设置InputFormat,OutputFormat, Map, Reduce,Partitioner,  KeyValue Class, Combine等一些列的Job必备的参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// create the job configuration
JobConf jobConf = new JobConf(conf, IndexUpdater.class);
jobConf.setJobName(this.getClass().getName() + "_"
    + System.currentTimeMillis());

// provided by application
FileInputFormat.setInputPaths(jobConf, inputPaths);
FileOutputFormat.setOutputPath(jobConf, outputPath);

jobConf.setNumMapTasks(numMapTasks);

// already set shards
jobConf.setNumReduceTasks(shards.length);

jobConf.setInputFormat(iconf.getIndexInputFormatClass());

// set by the system
jobConf.setMapOutputKeyClass(IndexUpdateMapper.getMapOutputKeyClass());
jobConf.setMapOutputValueClass(IndexUpdateMapper.getMapOutputValueClass());
jobConf.setOutputKeyClass(IndexUpdateReducer.getOutputKeyClass());
jobConf.setOutputValueClass(IndexUpdateReducer.getOutputValueClass());

jobConf.setMapperClass(IndexUpdateMapper.class);
jobConf.setPartitionerClass(IndexUpdatePartitioner.class);
jobConf.setCombinerClass(IndexUpdateCombiner.class);
jobConf.setReducerClass(IndexUpdateReducer.class);

jobConf.setOutputFormat(IndexUpdateOutputFormat.class);

return jobConf;

3、LineDocInputFormat(数据输入类)

从IndexUpdateConfiguration.getIndexInputFormatClass()可以获得当前默认使用的数据输入类org.apache.hadoop.contrib.index.example.LineDocInputFormat。

这里定义了org.apache.hadoop.contrib.index.example.LineDocRecordReader来解析数据,获取建立索引的命令(Insert, Update, Delete)和对应的数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
  public synchronized boolean next(DocumentID key, LineDocTextAndOp value)
      throws IOException {
    if (pos >= end) {
      return false;
    }

    // key is document id, which are bytes until first space
    if (!readInto(key.getText(), SPACE)) { // 把读到的第一个数据写入Key
      return false;
    }

    // read operation: i/d/u, or ins/del/upd, or insert/delete/update
    Text opText = new Text();
    if (!readInto(opText, SPACE)) {
      return false;
    }
    String opStr = opText.toString();
    DocumentAndOp.Op op;
    if (opStr.equals("i") || opStr.equals("ins") || opStr.equals("insert")) {
      op = DocumentAndOp.Op.INSERT;
    } else if (opStr.equals("d") || opStr.equals("del")
        || opStr.equals("delete")) {
      op = DocumentAndOp.Op.DELETE;
    } else if (opStr.equals("u") || opStr.equals("upd")
        || opStr.equals("update")) {
      op = DocumentAndOp.Op.UPDATE;
    } else {
      // default is insert
      op = DocumentAndOp.Op.INSERT;
    }
    value.setOp(op);

    if (op == DocumentAndOp.Op.DELETE) {
      return true;
    } else {
      // read rest of the line
      return readInto(value.getText(), EOL);
    }
  }

把InputStream offset到分隔符的数据写入到text

1
private boolean readInto(Text text, char delimiter) throws IOException

Sample 写道

0 ins apache dot org
2 ins apache
3 ins apache
4 ins apache

0 del
1 upd hadoop
2 del
3 upd hadoop

4、IndexUpdateMapper(最终形成IntermediateForm传递给Combiner和Reducer处理)

· ILocalAnalysis –>org.apache.hadoop.contrib.index.example.LineDocLocalAnalysis

把Text组成为Lucene需要的Document。

· DocumentAndOp

1
2
3
4
5
public class DocumentAndOp implements Writable {

  private Op op; // 
  private Document doc; // INSERT UPDATE
  private Term term; // DELETE UPDATE

· IntermediateForm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class IntermediateForm implements Writable {

  private final Collection<Term> deleteList;
  private RAMDirectory dir;
  private IndexWriter writer;
  private int numDocs;

  public void process(DocumentAndOp doc, Analyzer analyzer) throws IOException {
    if (doc.getOp() == DocumentAndOp.Op.DELETE
        || doc.getOp() == DocumentAndOp.Op.UPDATE) {
      deleteList.add(doc.getTerm());

    }

    if (doc.getOp() == DocumentAndOp.Op.INSERT
        || doc.getOp() == DocumentAndOp.Op.UPDATE) {

      if (writer == null) {
        // analyzer is null because we specify an analyzer with addDocument
        writer = createWriter();
      }

      writer.addDocument(doc.getDocument(), analyzer);
      numDocs++;
    }

  }

  public void process(IntermediateForm form) throws IOException {
    if (form.deleteList.size() > 0) {
      deleteList.addAll(form.deleteList);
    }

    if (form.dir.sizeInBytes() > 0) {
      if (writer == null) {
        writer = createWriter();
      }

      writer.addIndexesNoOptimize(new Directory[] { form.dir });
      numDocs++;
    }

  }

· HashingDistributionPolicy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class HashingDistributionPolicy implements IDistributionPolicy {

  private int numShards;

  public void init(Shard[] shards) {
    numShards = shards.length;
  }

  public int chooseShardForInsert(DocumentID key) {
    int hashCode = key.hashCode();
    return hashCode >= 0 ? hashCode % numShards : (-hashCode) % numShards;
  }

  public int chooseShardForDelete(DocumentID key) {
    int hashCode = key.hashCode();
    return hashCode >= 0 ? hashCode % numShards : (-hashCode) % numShards;
  }

}

IndexUpdateMapper.map(K, V, OutputCollector<Shard, IntermediateForm>, Reporter)

根据DocumentAndOp形成IntermediateForm,以及DistributionPolicy选择Shard,传入Combiner。

评注: 这里每条数据都要开启和关闭Writer,消耗应该不小。

5、IndexUpdateCombiner

把该节点的IntermediateForm合并成一个大的IntermediateForm集合。

评注: 感觉作用不是很大,合并减少的数据量有限; 但是却又要初始化和关闭一次Writer。

6、IndexUpdateReducer

把从Mapper传递来的IntermediateForm写入到ShardWriter。最终把Lucene索引写入到IndexPath下。

1
2
 public ShardWriter(FileSystem fs, Shard shard, String tempDir,
      IndexUpdateConfiguration iconf) throws IOException

在Reducer最后关闭ShardWriter时,由于要等待比较长的时间。这里使用一个新的线程来发送心跳。 使用hadoop/编写mapreduce程序 注意点(! 不要关闭mapreduce的超时)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
new Closeable() {
  volatile boolean closed = false;

  public void close() throws IOException {
    // spawn a thread to give progress heartbeats
    Thread prog = new Thread() {
      public void run() {
        while (!closed) {
          try {
            fReporter.setStatus("closing");
            Thread.sleep(1000);
          } catch (InterruptedException e) {
            continue;
          } catch (Throwable e) {
            return;
          }
        }
      }
    };

    try {
      prog.start();

      if (writer != null) {
        writer.close();
      }
    } finally {
      closed = true;
    }
  }
}.close();

· ShardWriter

把索引写到本地,等处理完了数据后,关闭IndexWriter后把索引库转入拷贝到HDFS持久化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
  // move the files created in the temp dir into the perm dir
  // and then delete the temp dir from the local FS
  private void moveFromTempToPerm() throws IOException {
    try {
      FileStatus[] fileStatus =
          localFs.listStatus(temp, LuceneIndexFileNameFilter.getFilter());
      Path segmentsPath = null;
      Path segmentsGenPath = null;

      // move the files created in temp dir except segments_N and segments.gen
      for (int i = 0; i < fileStatus.length; i++) {
        Path path = fileStatus[i].getPath();
        String name = path.getName();

        if (LuceneUtil.isSegmentsGenFile(name)) {
          assert (segmentsGenPath == null);
          segmentsGenPath = path;
        } else if (LuceneUtil.isSegmentsFile(name)) {
          assert (segmentsPath == null);
          segmentsPath = path;
        } else {
          fs.completeLocalOutput(new Path(perm, name), path);
        }
      }

      // move the segments_N file
      if (segmentsPath != null) {
        fs.completeLocalOutput(new Path(perm, segmentsPath.getName()),
            segmentsPath);
      }

      // move the segments.gen file
      if (segmentsGenPath != null) {
        fs.completeLocalOutput(new Path(perm, segmentsGenPath.getName()),
            segmentsGenPath);
      }
    } finally {
      // finally delete the temp dir (files should have been deleted)
      localFs.delete(temp);
    }
  }

【原文地址】

–END

使用hadoop编写mapreduce程序的注意点

编程时需要注意:

1、实例化job后,不要再使用原来的configuration,得通过job.getCongfigure()来进行参数的配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static Job createSubmittableJob(Configuration conf, String[] args) 
      throws IOException {
  String tableName = args[0];

  conf.set(TableInputFormat.INPUT_TABLE, tableName);
  conf.set(TableInputFormat.SCAN, 
      ScanAccessor.getTableInputFormatScan(conf, tableName));

  Job job = new Job(conf, 
      Index.class.getSimpleName() + "_" + tableName + ":" + Utils.now());
  job.setJarByClass(Index.class);

  // conf.set(..., ...)设置将不会生效
  job.getConfiguration().set(...

2、map输出的keyvalue与reduce的输出keyvalue对象不统一,这种情况不应该把reduce作为combine类。

1
2
3
4
5
6
7
8
9
10
job.setMapperClass(TokenizerMapper.class);
job.setCombinerClass(IntSumReducer.class);
job.setReducerClass(IntSumReducer.class);

job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(FloatWritable.class);

job.setOutputKeyClass(Text.class);
//job.setOutputValueClass(FloatWritable.class);
job.setOutputValueClass(Text.class);

这样的错误,出现后,如果不认认真真检查的话,比较难发现问题的!

如果map和reduce的keyvalue类型不同时,不要把Reduce的类作为Combine的处理类!

3、聚合类型的操作才使用reduce

  1. GOOD: sqoop导数据功能
  2. WORSE: hadoop contrib index (详…)

4、命令行参数的顺序

-D参数,以及Hadoop内置的参数, 必须放在class后面,不能跟在args

· ERROR

% hadoop jar hadoop-*-examples.jar sort -r numbers.seq sorted \ -inFormat org.apache.hadoop.mapred.SequenceFileInputFormat \ -outFormat org.apache.hadoop.mapred.SequenceFileOutputFormat \ -outkey org.apache.hadoop.io.IntWritable \ -outvalue org.apache.hadoop.io.Text

· OK

% hadoop jar hadoop-*-examples.jar sort -r \ -inFormat org.apache.hadoop.mapred.SequenceFileInputFormat \ -outFormat org.apache.hadoop.mapred.SequenceFileOutputFormat \ -outkey org.apache.hadoop.io.IntWritable \ -outvalue org.apache.hadoop.io.Text \ numbers.seq sorted

配置属性注意点:

  1. 开启trash <property> <name>fs.trash.interval</name> <value>720</value> </property>
  2. 去除mapreduce完成后”SUCCESS”,”history目录”
  3. 共享jvm
  4. 不要关闭mapreduce的超时 “` Configuration conf = … conf.set(“hadoop.job.history.user.location”, “none”); conf.setBoolean(“mapreduce.fileoutputcommitter.marksuccessfuljobs”, false);

    conf.set(“mapred.job.reuse.jvm.num.tasks”, “-1”);

    // conf.set(“mapred.task.timeout”, “0”); “` 可以在执行任务时,新建一个发送心跳的线程,告诉jobtracker当前的任务没有问题。

  5. pid的存放目录最好自定义。长期放置在tmp下的文件将会被清除。 http://winseclone.iteye.com/blog/1772989

     export HADOOP_PID_DIR=/var/hadoop/pids
    

Hadoop入门资料:

  1. 官网
  2. https://ccp.cloudera.com/display/DOC/Hadoop+Tutorial

【原文地址】

–END

Filter Mapping Url-pattern That Excludes Subdirectories

需求其实就是把eclipse osgi导出的应用嵌入到原有的ssh开发的程序中。 但是整合过程遇到一些问题。ssh会对资源进行拦截处理,导致OSGi获取不到请求,OSGi和ssh的应用最好分开管理。 可以利用SSH提供的excludePattern配置正则表达式来实现排除处理!

Struts拦截器配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<filter> 
  <filter-name>struts-cleanup</filter-name> 
  <filter-class> 
   org.apache.struts2.dispatcher.ActionContextCleanUp 
  </filter-class> 
</filter>
<filter-mapping> 
  <filter-name>struts-cleanup</filter-name> 
  <url-pattern>/*</url-pattern> 
</filter-mapping> 

<filter>
  <filter-name>struts</filter-name>
  <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>     
</filter>
<filter-mapping>
  <filter-name>struts</filter-name>
  <url-pattern>*.action</url-pattern>
</filter-mapping>
<filter-mapping>
  <filter-name>struts</filter-name>
  <url-pattern>*.do</url-pattern>
</filter-mapping>
<filter-mapping>
  <filter-name>struts</filter-name>
  <url-pattern>*.htm</url-pattern>
</filter-mapping>
<filter-mapping>
  <filter-name>struts</filter-name>
  <url-pattern>/struts/*</url-pattern>
</filter-mapping>

添加OSGi支持

把eclipse osgi应用嵌入需要在web.xml中添加:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<servlet id="bridge">
  <servlet-name>equinoxbridgeservlet</servlet-name>
  <servlet-class>org.eclipse.equinox.servletbridge.BridgeServlet</servlet-class>
  <init-param>
      <param-name>commandline</param-name>
      <param-value>-console</param-value>         
  </init-param>     
  <init-param>
      <param-name>enableFrameworkControls</param-name>
      <param-value>true</param-value>         
  </init-param>
  <init-param>
      <param-name>extendedFrameworkExports</param-name>
      <param-value></param-value>         
  </init-param> 
  <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
  <servlet-name>equinoxbridgeservlet</servlet-name>
  <url-pattern>
      /osgi/*
  </url-pattern>
</servlet-mapping>

整合遇到的问题及解决

由于struts的filter过滤了htm,导致osgi的htm文件被struts”劫”取了~~

经过一番挣扎,解决方法如下:

在struts过滤器中增加排除参数。

1
2
3
4
5
6
7
8
9
10
  <filter>
      <filter-name>struts</filter-name>
      <filter-class>
          org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
      </filter-class>
      <init-param>
          <param-name>struts.action.excludePattern</param-name>
          <param-value>/osgi/.*</param-value>
      </init-param>
  </filter>

为啥怎么弄,解释如下:

1 读取init-param初始化参数excludedPatterns

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
protected List<Pattern> excludedPatterns = null;

public void init(FilterConfig filterConfig) throws ServletException {
    InitOperations init = new InitOperations();
    try {
        FilterHostConfig config = new FilterHostConfig(filterConfig);
        init.initLogging(config);
        Dispatcher dispatcher = init.initDispatcher(config);
        init.initStaticContentLoader(config, dispatcher);

        prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);
        execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);
        this.excludedPatterns = init.buildExcludedPatternsList(dispatcher); // 获取不被Struts处理的请求Regex模式

        postInit(dispatcher, filterConfig);
    } finally {
        init.cleanup();
    }

}

2 使用excludedPatterns

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) 
                    throws IOException, ServletException {
    //父类向子类转:强转为httpReq请求、httpResp响应
    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;

  try {
      //。。。@@根据Regex模式(excludedPatterns)对请求进行处理
      if ( excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) {
          chain.doFilter(request, response);
      } else {
          request = prepare.wrapRequest(request);
          ActionMapping mapping = prepare.findActionMapping(request, response, true);
          if (mapping == null) {
              boolean handled = execute.executeStaticResourceRequest(request, response);
              if (!handled) {
                  chain.doFilter(request, response);
              }
          } else {
              execute.executeAction(request, response, mapping);
          }
      }
  } finally {
       prepare.cleanupRequest(request);
  }
}

后记

其实SSH就是对请求进行过滤拦截转发!Struts提供了不处理请求配置罢了。

看到的其他实现:

1
2
3
4
5
6
7
// First cast ServletRequest to HttpServletRequest.
HttpServletRequest hsr = (HttpServletRequest) request;

// Check if requested resource is not in /test folder.
if (!hsr.getServletPath().startsWith("/test/")) {
  // Not in /test folder. Do your thing here.
}

web.xml中的3种写法

  1. 完全匹配 /test/list.do
  2. 目录匹配 /test/*
  3. 扩展名匹配 *.do

servlet-mapping的重要规则:

  • 容器会首先查找完全匹配,如果找不到,再查找目录匹配,如果也找不到,就查找扩展名匹配。
  • 如果一个请求匹配多个“目录匹配”,容器会选择最长的匹配。

参考资源:


【原文地址】

–END

Win7下安装Fedora(linux)

(用虚拟接vmware安装,就不说了,这个相对来说没有心理压力。如果没装好,删掉就可以了。)

看了一个视频,热血沸腾的要转Linux,准备了老半天。

资料准备

1、查了一些资料,有硬盘安装安装Fedora,同时使用EasyBCD做多系统的启动(Win7下Fedora14硬盘或U盘安装指南http://www.linuxidc.com/Linux/2010-12/30459.htm)。

比较麻烦,手边也有空白光盘。

2、下载了fedora http://fedoraproject.org/zh_CN/get-fedora-options

刻录到光盘(最好不要用可擦写的刻;可擦写刻录的,老半天都进不去)

安装(多个硬盘也可以使用这个方法,不过更简单)

1)磁盘准备

在安装Fedora之前,最好先把要用的Linux磁盘分区准备好。

注意:Linux可以安装到逻辑分区的。硬盘一般可分四个主分区和一个拓展分区,由于没有注意到这个限制,在swap分区的时刻搞了好长的时间。可以把Linux安装分区全部放到拓展分区内的逻辑分区,这样就不会受到分区个数的影响。 同时方便以后修改和删除等操作,建议把linux(临时的系统)的硬盘空间的后面,方便以后回收和合并。

下图为安装为后的分区情况:

① 无效19.7G为为linux的”/“root路径
② 1.9G为Linux Swap缓冲分区

2)安装Linux系统

进入Fedora的live系统后,点击安装到硬盘的图标(Install to Hard Disk)。安装过程和其他的Win7系统的安装类似,有图形界面。

注意:选择启动引导信息的安装位置,这里选择安装Fedora的分区。好处就是不会干扰到原有的Win7系统。

① 在“Install boot loader on /dev/sda”选项的时刻,选择“Change device”。
② 在弹出的“Boot loader device”对话框中选择“First sector of boot partition - /dev/sda4”(/dev/sda4为我安装Fedora的主分区)

3)修改启动设置

安装完成重启之后,就会进入到Win7,根本不会有选择进入Fedora提示。这就说明安装的Fedora对于原来的Win7系统没有任何的影响。

① 下面安装grub工具来进行多系统的启动管理EasyBCD。

开机程序很好用的小工具:EasyBCD  下载安装

② 设置启动项(http://hi.baidu.com/rebornlinlin/blog/item/43dd70ce10bc8a29f9dc6114.html

以下两种方式都是可以的。

Fedora的sudo配置修改

在执行一些特权名命令的时刻,sudo命令总是的提示输入密码,很烦。(http://www.linuxidc.com/Linux/2010-12/30460.htm

打开终端Terminal输入:

1
su -

提示输入root用户密码。输入完root密码后回车,即可获得root权限。

再执行:

1
visudo

将会打开/etc/sudoers配置文件,找到

1
2
root ALL=(ALL) ## ALL这一行,紧跟此行增加一行
winse ALL=(ALL)  NOPASSWD:ALL

登陆后可以使用sudo,且不用再次输入密码。


【原文地址】

–END