04 配置HBase伪分布式环境

如果使用Hadoop3.1.x,建议配合Hbase2使用,如HBase2.2.3。

Hadoop version support matrix

  • √ = Tested to be fully-functional
  • ! = Known to not be fully-functional, or there are CVEs so we drop the support in newer minor releases
  • x = Not tested, may/may-not function
HBase-1.4.x HBase-1.6.x HBase-1.7.x HBase-2.2.x HBase-2.3.x
Hadoop-2.7.0 x x x x x
Hadoop-2.7.1+ x x x x
Hadoop-2.8.[0-2] x x x x x
Hadoop-2.8.[3-4] ! x x x x
Hadoop-2.8.5+ ! x x
Hadoop-2.9.[0-1] x x x x x
Hadoop-2.9.2+ ! x x
Hadoop-2.10.x ! !
Hadoop-3.1.0 x x x x x
Hadoop-3.1.1+ x x x
Hadoop-3.2.x x x x

1、解压

[hadoop@hadoop100 hbase-2.2.3]$ tar -zxvf hbase-2.2.3-bin.tar.gz -C /opt/pkg/

2、环境变量

[hadoop@hadoop100 hbase-2.2.3]$ vi conf/hbase-env.sh
[hadoop@hadoop100 hbase-2.2.3]$ sudo vim /etc/profile.d/env.sh 

# JAVA_HOME
export JAVA_HOME=/opt/pkg/java
export PATH=$JAVA_HOME/bin:$PATH

# HADOOP_HOME
export HADOOP_HOME=/opt/pkg/hadoop-3.1.4
export PATH=$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$PATH

# HBASE_HOME
export HBASE_HOME=/opt/pkg/hbase-2.2.3
export PATH=$HBASE_HOME/bin:$PATH

最后使用source命令使配置生效

[hadoop@hadoop100 hbase-2.2.3]$ source /etc/profile.d/env.sh

3、配置

拷贝hadoop的hdfs-site.xml和core-site.xml软链接到hbase的conf目录下面


# core-site.xml
$ ln -s /opt/pkg/hadoop-2.7.3/etc/hadoop/hdfs-site.xml /opt/pkg/hbase-2.2.3/conf/hdfs-site.xml
# hdfs-site.xml
$ ln -s /opt/pkg/hadoop-2.7.3/etc/hadoop/core-site.xml /opt/pkg/hbase-2.2.3/conf/core-site.xml

修改hbase的conf/hbase-env.sh

# The java implementation to use.  Java 1.7+ required.
# export JAVA_HOME=/usr/java/jdk1.6.0/
export JAVA_HOME=/opt/pkg/java

# Configure PermSize. Only needed in JDK7. You can safely remove it for JDK8+
# export HBASE_MASTER_OPTS="$HBASE_MASTER_OPTS -XX:PermSize=128m -XX:MaxPermSize=128m"
# export HBASE_REGIONSERVER_OPTS="$HBASE_REGIONSERVER_OPTS -XX:PermSize=128m -XX:MaxPermSize=128m"

# Tell HBase whether it should manage it's own instance of Zookeeper or not.
# export HBASE_MANAGES_ZK=true
  • 首先,需要修改JAVA_HOME为真实JDK路径

  • Configure PermSize.下面的2条export语句只是针对JDK7的优化,如果不用JDK7则可以删除或者注释掉

  • 默认情况,由HBase自行管理内置在其内的Zookeeper服务

    • 如果想要使用外部Zookeeper集群来进行管理,需要设置
    export HBASE_MANAGES_ZK=false

修改hbase的核心配置文件conf/hbase-site.xml

<configuration>
    <!-- Hbase在HDFS上的根目录 -->
    <property>
        <name>hbase.rootdir</name>
        <value>hdfs://hadoop100:8020/hbase</value>
    </property>
    <!-- HBase在ZooKeeper上的快照数据存储位置 -->
    <property>
        <name>hbase.zookeeper.property.dataDir</name>
        <value>/opt/pkg/hadoop/data/tmp/hbase-zkdata</value>
    </property>
    <!-- 是否以集群的方式运行 -->
    <property>
        <name>hbase.cluster.distributed</name>
        <value>true</value>
    </property>
    <!-- Zookeeper集群的所有主机,如有多个则逗号分隔 -->
    <property>
        <name>hbase.zookeeper.quorum</name>
        <value>hadoop100</value>
    </property>
</configuration>
  • hbase.rootdir是hbase存储在HDFS上的数据的根目录,里面存储着所有region的数据

  • 无论是伪分布式还是全分布式,hbase.cluster.distributed都需要设置true

    • 如果设成false,则hbase和zookeeper会在一个JVM进程里运行
  • hbase.zookeeper.quorum的主机名默认是localhost,应改为zookeeper集群中所有机器的主机名,多个主机名之间使用逗号分隔

  • zookeeper的端口默认都是2181,如果不是可以添加

问题:

java.lang.IllegalStateException: The procedure WAL relies on the ability to hsync for proper operation during component failures, but the underlying filesystem does not support doing so. Please check the config value of 'hbase.procedure.store.wal.use.hsync' to set the desired level of robustness and ensure the config value of 'hbase.wal.dir' points to a FileSystem mount that can provide it.

解决:

  • 在hbase-site.xml增加配置
<property>
    <name>hbase.unsafe.stream.capability.enforce</name>
    <value>false</value>
</property>

4、测试

首先启动hadoop的dfs相关进程

[hadoop@hadoop100 lib]$ start-dfs.sh 

等半分钟后启动Hbase

[hadoop@hadoop100 lib]$ start-hbase.sh 
hadoop100: starting zookeeper, logging to /opt/pkg/hbase-2.2.3/logs/hbase-hadoop-zookeeper-hadoop100.out
starting master, logging to /opt/pkg/hbase-2.2.3/logs/hbase-hadoop-master-hadoop100.out
starting regionserver, logging to /opt/pkg/hbase-2.2.3/logs/hbase-hadoop-1-regionserver-hadoop100.out

使用hbase shell测试


[hadoop@hadoop100 lib]$ hbase shell
HBase Shell; enter 'help<RETURN>' for list of supported commands.
Type "exit<RETURN>" to leave the HBase Shell
Version 2.2.3, r67592f3d062743907f8c5ae00dbbe1ae4f69e5af, Tue Oct 25 18:10:20 CDT 2020

hbase(main):001:0> status
1 active master, 0 backup masters, 1 servers, 0 dead, 2.0000 average load

hbase(main):002:0> list
TABLE                                                                                                   
0 row(s) in 0.0490 seconds

=> []

hbase(main):004:0> create 'wc','cf'
0 row(s) in 4.6740 seconds

=> Hbase::Table - wc
hbase(main):005:0> put 'wc','hello', 'cf:word', 'word'
0 row(s) in 0.2030 seconds

hbase(main):006:0> scan 'wc'
ROW                         COLUMN+CELL                                                                 
 hello                      column=cf:word, timestamp=1610209834376, value=word                         
1 row(s) in 0.0590 seconds

hbase(main):007:0> 

界面

hbase的Master管理界面地址: http://hadoop100:16010

image-20210110012902737

hbase的RegionServer管理界面地址: http://hadoop100:16301

image-20210110013140999

常见问题

注意:如果启动HBase Shell时遇到警告:

[hadoop@hadoop100 hbase-2.2.3]$ hbase shell
SLF4J: Class path contains multiple SLF4J bindings.

原因是hadoop和hbase的jar包冲突了,解决办法,将hbase/lib下面的相同slf4j-log4j12的jar包改名即可

[hadoop@hadoop100 lib]$ mv slf4j-log4j12-1.7.5.jar slf4j-log4j12-1.7.5.jar.backup

Views: 45

03- Zookeeper安装和配置

1、下载和安装

下载,解压,配置环境变量就不多说了,和其他框架都大致一样,版本选择3.14

2、单机单服务

zoo.cfg

tickTime=2000
initLimit=10
syncLimit=5
dataDir=/opt/tmp/zk
dataLogDir=/opt/tmp/zk-log

3、单机多服务

img

三个配置文件zoo-1.cfg、zoo-2.cfg、zoo-3.cfg

tickTime=2000
initLimit=10
syncLimit=5
dataDir=/opt/tmp/zk-1(zk-2|zk-3)
dataLogDir=/opt/tmp/zk-log-1(zk-log-2|zk-log-3)
clientPort=2181(2182|2183)

4lw.commands.whitelist=*
server.1=localhost:2891:3891
server.2=localhost:2892:3892
server.3=localhost:2893:3893

在三个dataDir里面分别建立一个myid文件, 里面分别保存数字1, 2, 3,对应配置中的server。

4、zk服务相关命令

zkServer.sh start|status|stop zoo-1|2|3.cfg

新版本的kafka里面自带zookeeper,你可以在bin里面找到自带的zookeeper相关命令

zookeeper的提供了模板配置文件zoo-sample.cfg,可以拷贝修改成为自己的配置

Views: 52

02 – Hadoop3.1.4的单机安装

1、准备工作

(1)主机名映射S

# vi /etc/hosts vi /etc/hosts

#127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
#::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

192.168.186.100 hadoop100

注意:宿主的WIndows系统也要一样配置hadoop100并且映射到虚拟机的ip上

(2)SSH免密登录

Centos7默认安装了sshd服务,可使用ssh协议远程开启对其他主机shell的服务。

如果没有可以使用yum安装

sudo yum -y install openssl-devel

由于Hadoop集群的机器之间ssh通信默认需要输入密码,在集群运行时我们不可能为每一次通信都手动输入密码,因此需要配置机器之间的ssh的免密登录。

即使是单机伪分布式的Hadoop环境也不例外,一样需要配置本地对本地ssh连接的免密。

hadoop@hadoop100 ~]$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/hadoop/.ssh/id_rsa): 
Created directory '/home/hadoop/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/hadoop/.ssh/id_rsa.
Your public key has been saved in /home/hadoop/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:yQYChs4eniVLeICaI2bCB9HopbXUBE9v0lpLjBACUnM hadoop@hadoop100
The key's randomart image is:
+---[RSA 2048]----+
|==O+Eo           |
|=+.O+.=          |
|Bo* o+.B         |
|B%.+ .*o..       |
|OoB  . .S        |
| =     .         |
|                 |
|                 |
|                 |
+----[SHA256]-----+
[hadoop@hadoop100 ~]$ cd ~/.ssh/
[hadoop@hadoop100 .ssh]$ cat id_rsa.pub >> authorized_keys
[hadoop@hadoop100 .ssh]$ chmod 600 authorized_keys 
[hadoop@hadoop100 .ssh]$ ssh hadoop@hadoop100
The authenticity of host 'hadoop100 (192.168.186.100)' can't be established.
ECDSA key fingerprint is SHA256:aGLhdt3bIuqtPgrFWnhgrfTKUbDh4CWVTfIgr5E5oV0.
ECDSA key fingerprint is MD5:b8:bd:b3:65:fe:77:2c:06:2d:ec:58:3a:97:51:dd:ca.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'hadoop100,192.168.186.100' (ECDSA) to the list of known hosts.
Last login: Sat Jan  9 10:16:53 2021 from 192.168.186.1
[hadoop@hadoop100 ~]$ exit
登出
Connection to hadoop100 closed.
[hadoop@hadoop100 .ssh]$

大致流程:

  1. ssh-keygen命令生成RSA加密的密钥对(公钥和私钥)
  2. 将公钥添加到~/.ssh目录下的authorized_keys文件中
    1. 如机器A需要SSH连接到机器B,就需要将机器A生成的公钥发送到机器B的authorized_keys文件中进行认证
    2. 如果需要和自己通信,就把自己生成的公钥放在自己的authorized_keys文件中即可
  3. 使用ssh命令连接本地终端,如果不需要输入密码则本地的免密配置成功

(3)配置时间同步

集群中的通信和文件传输一般是以系统时间作为约定条件的。所以当集群中机器之间系统如果不一致可能导致各种问题发生,比如访问时间过长,甚至失败。所以配置机器之间的时间同步非常重要。

另外,单机伪分布式可以无需配置时间同步服务器,只需要定时使用nptdate命令校准即可。

以下操作必须切换成root用户

安装ntp

[hadoop@hadoop100 .ssh]$ su root
密码:
[root@hadoop100 .ssh]# rpm -qa | grep ntp
[root@hadoop100 .ssh]# yum install -y ntp
  1. rpm -qa查询是否已经安装了ntp
  2. 如果没有则安装ntp

修改/etc/sysconfig/ntpd,增加如下内容(让硬件时间和系统时间一起同步)

SYNC_HWCLOCK=yes

(4)定时校正时间

使用ntpdate命令手动的校正时间。

[root@hadoop100 .ssh]#  ntpdate cn.pool.ntp.org
 9 Jan 11:49:13 ntpdate[11274]: adjust time server 185.209.85.222 offset -0.016417 sec
[root@hadoop100 .ssh]# date
2021年 01月 09日 星期六 11:49:32 CST

观察时间是否与你所在的时区一致,如果不一致请查看【常见问题】寻找解决办法。

接下来使用crontab定时任务来每10分钟校准一次

# 编辑新的定时任务
[root@hadoop100 .ssh]# crontab -e
*/10 * * * * /usr/sbin/ntpdate cn.pool.ntp.org

# 查看root账户下所有定时任务
[root@hadoop100 .ssh]# crontab -l
*/10 * * * * /usr/sbin/ntpdate cn.pool.ntp.org

为了测试,先修改时间为错误时间

[root@hadoop100 .ssh]# date -s '2020-1-1 01:01'
2020年 01月 01日 星期三 01:01:00 CST 

10分钟后再次查看

[root@hadoop100 .ssh]# date
2021年 01月 09日 星期六 14:12:12 CST

说明自动校准已经设置

默认crontab定时任务就是开机自动启动的

[root@hadoop100 .ssh]# systemctl list-unit-files | grep crond
crond.service                                 enabled 

(5)统一目录结构

接下来切换用户为hadoop账户

[hadoop@hadoop100 opt]$ sudo mkdir /opt/download
[hadoop@hadoop100 opt]$ sudo mkdir /opt/data
[hadoop@hadoop100 opt]$ sudo mkdir /opt/bin
[hadoop@hadoop100 opt]$ sudo mkdir /opt/tmp
[hadoop@hadoop100 opt]$ sudo mkdir /opt/pkg

# 更改opt下目录的用户及其所在用户组为hadoop
[hadoop@hadoop100 opt]$ sudo chown hadoop:hadoop /opt/*
[hadoop@hadoop100 opt]$ ls
bin  data  download  pkg  tmp
[hadoop@hadoop100 opt]$ ll
总用量 0
drwxr-xr-x. 2 hadoop hadoop 6 1月   9 14:29 bin
drwxr-xr-x. 2 hadoop hadoop 6 1月   9 14:29 data
drwxr-xr-x. 2 hadoop hadoop 6 1月   9 14:29 download
drwxr-xr-x. 2 hadoop hadoop 6 1月   9 14:37 pkg
drwxr-xr-x. 2 hadoop hadoop 6 1月   9 14:36 tmp

目录规划如下:

/opt/ 
    ├── bin         # shell脚本
    ├── data        # 程序需要使用的数据
    ├── download    # 下载的软件安装包
    ├── pkg         # 解压方式安装的软件
    └── tmp         # 存放程序生成的临时文件

2、安装jdk

检查是否已经安装过JDK

[hadoop@hadoop100 download]$ rpm -qa | grep java
# 或者
[hadoop@hadoop100 download]$ yum list installed | grep java

如果没有jdk或者jdk版本低于1.8,则重新安装jdk1.8

下载安装包到/opt/download/然后解压到/opt/pkg

[hadoop@hadoop100 download]$ tar -zxvf jdk-8u261-linux-x64.tar.gz 
[hadoop@hadoop100 download]$ mv jdk1.8.0_261 /opt/pkg/java

配置java环境变量

确认jdk的解压路径

[hadoop@hadoop100 java]$ pwd
/opt/pkg/java

编辑/etc/profile.d/env.sh配置文件(没有则创建)

[hadoop@hadoop100 java]$ sudo vim /etc/profile.d/env.sh

在后面添加新的环境变量配置

# JAVA_HOME
export JAVA_HOME=/opt/pkg/java
export PATH=$JAVA_HOME/bin:$PATH

使新的环境变量立刻生效

[hadoop@hadoop100 java]$ source /etc/profile.d/env.sh

验证环境变量

[hadoop@hadoop100 java]$ java -version
[hadoop@hadoop100 java]$ java
[hadoop@hadoop100 java]$ javac

3、安装Hadoop

  1. 解压

    [hadoop@hadoop100 hadoop]$ tar -zxvf hadoop.tar.gz -C /opt/pkg/
  2. 编辑/etc/profile.d/env.sh配置文件,添加环境变量

    # JAVA_HOME
    export JAVA_HOME=/opt/pkg/java
    export PATH=$JAVA_HOME/bin:$PATH
    # HADOOP_HOME
    export HADOOP_HOME=/opt/pkg/hadoop
    export PATH=$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$PATH
  3. 使新的环境变量立刻生效

    [hadoop@hadoop100 opt]$ source /etc/profile.d/env.sh
  4. 验证

    [hadoop@hadoop100 opt]$ hadoop version
  5. 修改相关命令执行环境

    hadoop/etc/hadoop/hadoop-env.sh - hadoop命令执行环境

      # The java implementation to use.
      export JAVA_HOME=/opt/pkg/java
    • 修改JAVA_HOME为真实JDK路径即可
  6. hadoop/etc/hadoop/yarn.env.sh - yarn命令执行环境

      # export JAVA_HOME=/home/y/libexec/jdk1.6.0/
      export JAVA_HOME=/opt/pkg/java
    • 添加JAVA_HOME为真实JDK路径即可
  7. hadoop/etc/hadoop/mapred.env.sh - map reducer命令执行环境

      # export JAVA_HOME=/home/y/libexec/jdk1.6.0/
      export JAVA_HOME=/opt/pkg/java
    • 添加JAVA_HOME为真实JDK路径即可
  8. 修改配置-实现伪分布式环境,来到 hadoop/etc/hadoop/,修改以下配置文件

    hadoop/etc/hadoop/core-site.xml - 核心配置文件

      <configuration>
          <!-- 指定NameNode的地址和端口. -->
          <property>
              <name>fs.defaultFS</name>
              <value>hdfs://hadoop100:8020</value>
          </property>
          <!-- 指定HDFS系统运行时产生的文件的存储目录. -->
          <property>
              <name>hadoop.tmp.dir</name>
              <value>/opt/pkg/hadoop/data/tmp</value>
          </property>
          <!--  缓冲区大小,实际工作中根据服务器性能动态调整;默认值4096 -->
       <property>
           <name>io.file.buffer.size</name>
           <value>4096</value>
       </property>
       <!--  开启hdfs的垃圾桶机制,删除掉的数据可以从垃圾桶中回收,单位分钟;默认值0 -->
       <property>
           <name>fs.trash.interval</name>
           <value>10080</value>
       </property>
    </configuration>
    1. 主机名修改成本机的主机名

    2. hadoop.tmp.dir十分重要,保存这个hadoop集群中namenode和datanode的所有数据

  9. hadoop/etc/hadoop/hdfs-site.xml - HDFS相关配置

      <configuration>
          <!-- 设置HDFS中的数据副本数. -->
          <property>
             <name>dfs.replication</name>
             <value>1</value>
          </property>
           <!-- 设置Hadoop的Secondary NameNode的主机配置 -->
          <property>
             <name>dfs.namenode.secondary.http-address</name>
             <value>hadoop100:9868</value>
          </property>
          <property>
              <name>dfs.namenode.http-address</name>
              <value>hadoop100:9870</value>
          </property>
          <!-- 是否检查操作HDFS文件系统的用户权限. -->
          <property>
          <name>dfs.permissions</name>
          <value>false</value>
       </property>
    </configuration>
    • dfs.replication默认是3,为了节省虚拟机资源,这里设置为1

    • 全分布式情况下,SecondaryNameNode和NameNode 应分开部署

    • dfs.namenode.secondary.http-address默认就是本地,如果是伪分布式可以不用配置

  10. hadoop/etc/hadoop/mapred-site.xml - mapreduce 相关配置

    <configuration>
        <!-- 指定MapReduce程序由Yarn进行调度. -->
        <property>
            <name>mapreduce.framework.name</name>
            <value>yarn</value>
        </property>
            <!-- Mapreduce的Job历史记录服务器主机端口设置. -->
        <property>
            <name>mapreduce.jobhistory.address</name>
            <value>hadop100:10020</value>
        </property>
            <!-- Mapreduce的Job历史记录的Webapp端地址. -->
        <property>
            <name>mapreduce.jobhistory.webapp.address</name>
            <value>hadoop100:19888</value>
        </property>
    
        <property>
            <name>yarn.app.mapreduce.am.env</name>
            <value>HADOOP_MAPRED_HOME=/opt/pkg/hadoop</value>
        </property>
        <property>
            <name>mapreduce.map.env</name>
            <value>HADOOP_MAPRED_HOME=/opt/pkg/hadoop</value>
        </property>
        <property>
            <name>mapreduce.reduce.env</name>
            <value>HADOOP_MAPRED_HOME=/opt/pkg/hadoop</value>
        </property>
    
    </configuration>

    • mapreduce.jobhistory相关配置是可选配置,用于查看MR任务的历史日志

      • 这里主机名千万不要弄错,不然任务执行会失败,且不容易找原因
        • 需要手动启动MapReduceJobHistory后台服务才能在Yarn的页面打开历史日志
  11. 配置 yarn-site.xml

      <configuration>
          <!-- 设置Yarn的ResourceManager节点主机名. -->
        <property>
           <name>yarn.resourcemanager.hostname</name>
           <value>hadoop100</value>
        </property>
           <!-- 设置Mapper端将数据发送到Reducer端的方式. -->
        <property>
           <name>yarn.nodemanager.aux-services</name>
           <value>mapreduce_shuffle</value>
        </property>
          <!-- 是否开启日志手机功能. -->
        <property>
           <name>yarn.log-aggregation-enable</name>
           <value>true</value>
        </property>
          <!-- 日志保留时间(7天). -->
        <property>
           <name>yarn.log-aggregation.retain-seconds</name>
           <value>604800</value>
        </property>
          <!-- 如果vmem、pmem资源不够,会报错,此处将资源监察置为false -->
       <property>
           <name>yarn.nodemanager.vmem-check-enabled</name>
           <value>false</value>
       </property>
       <property>
           <name>yarn.nodemanager.pmem-check-enabled</name>
           <value>false</value>
       </property>
    </configuration>
  12. workers DataNode 节点配置

      vi workers
      [hadoop@hadoop100 hadoop]$ vi workers
      hadoop100
    • 如果是伪分布式可以不进行修改,默认是localhost, 也可以改成本机的主机名
  • 全分布式配置则需要每行输入一个DataNode主机名

    • 注意不要有空格和空行,因为其他脚本会获取相关主机名信息

4、格式化名称节点

格式化:HDFS(NameNode)

hadoop@hadoop100 hadoop]$ hdfs namenode -format

21/01/09 19:27:21 INFO namenode.NameNode: STARTUP_MSG: 
/************************************************************
STARTUP_MSG: Starting NameNode
STARTUP_MSG:   host = hadoop100/192.168.186.100
STARTUP_MSG:   args = [-format]
STARTUP_MSG:   version = 2.7.3
************************************************************/
21/01/09 19:27:21 INFO namenode.NameNode: registered UNIX signal handlers for [TERM, HUP, INT]
21/01/09 19:27:21 INFO namenode.NameNode: createNameNode [-format]
Formatting using clusterid: CID-08318e9e-e202-48f3-bcb1-548ca50310c9
21/01/09 19:27:22 INFO util.GSet: Computing capacity for map BlocksMap
21/01/09 19:27:22 INFO util.GSet: VM type       = 64-bit
21/01/09 19:27:22 INFO util.GSet: 2.0% max memory 966.7 MB = 19.3 MB
21/01/09 19:27:22 INFO util.GSet: capacity      = 2^21 = 2097152 entries
21/01/09 19:27:22 INFO blockmanagement.BlockManager: dfs.block.access.token.enable=false
21/01/09 19:27:22 INFO blockmanagement.BlockManager: defaultReplication         = 1
21/01/09 19:27:22 INFO blockmanagement.BlockManager: maxReplication             = 512
21/01/09 19:27:22 INFO blockmanagement.BlockManager: minReplication             = 1
21/01/09 19:27:22 INFO blockmanagement.BlockManager: maxReplicationStreams      = 2
21/01/09 19:27:22 INFO blockmanagement.BlockManager: replicationRecheckInterval = 3000
21/01/09 19:27:22 INFO blockmanagement.BlockManager: encryptDataTransfer        = false
21/01/09 19:27:22 INFO blockmanagement.BlockManager: maxNumBlocksToLog          = 1000
21/01/09 19:27:22 INFO namenode.FSNamesystem: fsOwner             = hadoop (auth:SIMPLE)
21/01/09 19:27:22 INFO namenode.FSNamesystem: supergroup          = supergroup
21/01/09 19:27:22 INFO namenode.FSNamesystem: isPermissionEnabled = false
21/01/09 19:27:22 INFO namenode.FSNamesystem: HA Enabled: false
21/01/09 19:27:22 INFO namenode.FSNamesystem: Append Enabled: true
21/01/09 19:27:23 INFO common.Storage: Storage directory /opt/pkg/hadoop/data/tmp/dfs/name has been successfully formatted.
/************************************************************
SHUTDOWN_MSG: Shutting down NameNode at hadoop100/192.168.186.100
************************************************************/
  • 注意格式化后会在hdfs-site.xml中指定的hadoop.tmp.dir目录中生成相关数据

  • 其中NameNode和DataNode的数据文件夹中应保存着一致的ClusterID(CID)

    [hadoop@hadoop100 hadoop]$ cat /opt/pkg/hadoop/data/tmp/dfs/name/current/VERSION
    #Sat Jan 09 19:27:23 CST 2021
    namespaceID=637773384
    clusterID=CID-08318e9e-e202-48f3-bcb1-548ca50310c9
    cTime=0
    storageType=NAME_NODE
    blockpoolID=BP-1926974917-192.168.186.100-1610191643341
    layoutVersion=-63
    
    [hadoop@hadoop100 hadoop]$ cat /opt/pkg/hadoop/data/tmp/dfs/data/current/VERSION 
    #Sat Jan 09 19:33:49 CST 2021
    storageID=DS-6abf02d0-274c-4b7a-9d1d-05ed7d73636a
    clusterID=CID-08318e9e-e202-48f3-bcb1-548ca50310c9
    cTime=0
    datanodeUuid=44ff2304-01b1-4d8a-8a42-a2ad6e62ebba
    storageType=DATA_NODE
    layoutVersion=-56
    
    • 如果多次格式化就会导致NamdeNode新生成的CID和DataNode不一致
    • 解决办法,停止集群,将DN的CID修改成和NN的CID一致,再启动集群

5、运行和测试

启动Hadoop环境,刚启动Hadoop的HDFS系统后会有几秒的安全模式,安全模式期间无法进行任何数据处理,这也是为什么不建议使用start-all.sh脚本一次性启动DFS进程和Yarn进程,而是先启动dfs后过30秒左右再启动Yarn相关进程。

启动DFS进程:

[hadoop@hadoop100 hadoop]$ start-dfs.sh
Starting namenodes on [hadoop100]
hadoop100: starting namenode, logging to /opt/pkg/hadoop/logs/hadoop-hadoop-namenode-hadoop100.out
hadoop100: starting datanode, logging to /opt/pkg/hadoop/logs/hadoop-hadoop-datanode-hadoop100.out
Starting secondary namenodes [hadoop100]
hadoop100: starting secondarynamenode, logging to /opt/pkg/hadoop/logs/hadoop-hadoop-secondarynamenode-hadoop100.out

启动YARN进程:

[hadoop@hadoop100 hadoop]$ start-yarn.sh
starting yarn daemons
starting resourcemanager, logging to /opt/pkg/hadoop/logs/yarn-hadoop-resourcemanager-hadoop100.out
hadoop100: starting nodemanager, logging to /opt/pkg/hadoop/logs/yarn-hadoop-nodemanager-hadoop100.out

启动MapReduceJobHistory后台服务 - 用于查看MR执行的历史日志

[hadoop@hadoop100 mapreduce]$ mr-jobhistory-daemon.sh start historyserver

停止集群(可以做成脚本)

stop-dfs.sh
stop-yarn.sh 
# 已过时 mr-jobhistory-daemon.sh stop historyserver
mapred --daemon stop historyserver

单个进程逐个启动

# 在主节点上使用以下命令启动 HDFS NameNode: 
# 已过时 hadoop-daemon.sh start namenode 
hdfs --daemon start namenode

# 在主节点上使用以下命令启动 HDFS SecondaryNamenode: 
# 已过时 hadoop-daemon.sh start secondarynamenode 
hdfs --daemon start secondarynamenode

# 在每个从节点上使用以下命令启动 HDFS DataNode: 
# 已过时 hadoop-daemon.sh start datanode
hdfs --daemon start datanode

# 在主节点上使用以下命令启动 YARN ResourceManager: 
# 已过时 yarn-daemon.sh start resourcemanager 
yarn --daemon start resourcemanager

# 在每个从节点上使用以下命令启动 YARN nodemanager: 
# 已过时 yarn-daemon.sh start nodemanager 
yarn --daemon start nodemanager

以上脚本位于$HADOOP_HOME/sbin/目录下。如果想要停止某个节点上某个角色,只需要把命令中的start 改为stop 即可。

Web界面进行验证

HDFS:http://hadoop100:9870

image-20210109193629973

Yarn:http://hadoop100:8088

image-20210109193653338

执行jps命令,看看是否会有如下进程:

[hadoop@hadoop100 hadoop]$ jps
14608 NodeManager
14361 SecondaryNameNode
14203 DataNode
14510 ResourceManager
14079 NameNode

14910 Jps

使用官方自带的示例程序测试

[hadoop@hadoop100 mapreduce]$ cd /opt/pkg/hadoop/share/hadoop/mapreduce
[hadoop@hadoop100 mapreduce]$ hadoop jar hadoop-mapreduce-examples-2.7.3.jar wordcount
Usage: wordcount <in> [<in>...] <out>

准备输入文件,并上传到HDFS系统

[hadoop@hadoop100 input]$ cat /opt/data/mapred/input/wc.txt
hadoop hadoop hadoop
hi hi hi hello hadoop
hello world hadoop

[hadoop@hadoop100 input]$ hadoop fs -mkdir -p /input/wc
[hadoop@hadoop100 input]$ hadoop fs -put wc.txt /input/wc/
Found 1 items
-rw-r--r--   1 hadoop supergroup         62 2021-01-09 20:15 /input/wc/wc.txt

[hadoop@hadoop100 input]$ hadoop fs -cat /input/wc/wc.txt
hadoop hadoop hadoop
hi hi hi hello hadoop
hello world hadoop

运行示例wordcount程序,并将结果输出到/output/wc之中

[hadoop@hadoop100 mapreduce]$ cd /opt/pkg/hadoop/share/hadoop/mapreduce
[hadoop@hadoop100 mapreduce]$ hadoop jar hadoop-mapreduce-examples-2.7.3.jar wordcount /input/wc/ /output/wc/
21/01/09 20:23:27 INFO client.RMProxy: Connecting to ResourceManager at hadoop100/192.168.186.100:8032
21/01/09 20:23:28 INFO input.FileInputFormat: Total input paths to process : 1
21/01/09 20:23:28 INFO mapreduce.JobSubmitter: number of splits:1
21/01/09 20:23:29 INFO mapreduce.JobSubmitter: Submitting tokens for job: job_1610194940581_0001
21/01/09 20:23:29 INFO impl.YarnClientImpl: Submitted application application_1610194940581_0001
21/01/09 20:23:29 INFO mapreduce.Job: The url to track the job: http://hadoop100:8088/proxy/application_1610194940581_0001/
21/01/09 20:23:29 INFO mapreduce.Job: Running job: job_1610194940581_0001
21/01/09 20:23:43 INFO mapreduce.Job: Job job_1610194940581_0001 running in uber mode : false
21/01/09 20:23:43 INFO mapreduce.Job:  map 0% reduce 0%
21/01/09 20:23:52 INFO mapreduce.Job:  map 100% reduce 0%
21/01/09 20:24:00 INFO mapreduce.Job:  map 100% reduce 100%
21/01/09 20:24:01 INFO mapreduce.Job: Job job_1610194940581_0001 completed successfully
21/01/09 20:24:02 INFO mapreduce.Job: Counters: 49
    File System Counters
        FILE: Number of bytes read=52
        FILE: Number of bytes written=237407
        FILE: Number of read operations=0
        FILE: Number of large read operations=0
        FILE: Number of write operations=0
        HDFS: Number of bytes read=164
        HDFS: Number of bytes written=30
        HDFS: Number of read operations=6
        HDFS: Number of large read operations=0
        HDFS: Number of write operations=2
    Job Counters 
        Launched map tasks=1
        Launched reduce tasks=1
        Data-local map tasks=1
        Total time spent by all maps in occupied slots (ms)=7041
        Total time spent by all reduces in occupied slots (ms)=5566
        Total time spent by all map tasks (ms)=7041
        Total time spent by all reduce tasks (ms)=5566
        Total vcore-milliseconds taken by all map tasks=7041
        Total vcore-milliseconds taken by all reduce tasks=5566
        Total megabyte-milliseconds taken by all map tasks=7209984
        Total megabyte-milliseconds taken by all reduce tasks=5699584
    Map-Reduce Framework
        Map input records=3
        Map output records=11
        Map output bytes=106
        Map output materialized bytes=52
        Input split bytes=102
        Combine input records=11
        Combine output records=4
        Reduce input groups=4
        Reduce shuffle bytes=52
        Reduce input records=4
        Reduce output records=4
        Spilled Records=8
        Shuffled Maps =1
        Failed Shuffles=0
        Merged Map outputs=1
        GC time elapsed (ms)=146
        CPU time spent (ms)=2570
        Physical memory (bytes) snapshot=339308544
        Virtual memory (bytes) snapshot=4163043328
        Total committed heap usage (bytes)=219676672
    Shuffle Errors
        BAD_ID=0
        CONNECTION=0
        IO_ERROR=0
        WRONG_LENGTH=0
        WRONG_MAP=0
        WRONG_REDUCE=0
    File Input Format Counters 
        Bytes Read=62
    File Output Format Counters 
        Bytes Written=30
  • 注意,输入是文件夹,可以指定多个
  • 输出是一个必须不能存在的文件夹路径
  • 计算结果会写入到output指定的文件夹中

查看保存在HDFS上的结果

[hadoop@hadoop100 mapreduce]$ hadoop fs -ls /output/wc/
Found 2 items
-rw-r--r--   1 hadoop supergroup          0 2021-01-09 20:23 /output/wc/_SUCCESS
-rw-r--r--   1 hadoop supergroup         30 2021-01-09 20:23 /output/wc/part-r-00000
[hadoop@hadoop100 mapreduce]$ hadoop fs -cat /output/wc/part-r-00000
hadoop  5
hello   2
hi  3
world   1

在MR任务执行时,可以通过Yarn的界面查看进度

image-20210109203547507

执行完毕以后点击TrackingUI下的History可以查看历史日志记录

如果跳转页面报404说明没有启动JobHistoryServer服务

[hadoop@hadoop100 mapreduce]$ mr-jobhistory-daemon.sh start historyserver

image-20210109224932545

也可以在HDFS的Web界面上查看结果

image-20210109213522691

Utilities -> HDFS browser -> /output/wc/ -> click part-r-00000 -> download part-r-00000

[hadoop@hadoop100 hadoop]$ stop-all.sh

This script is Deprecated. Instead use stop-dfs.sh and stop-yarn.sh
Stopping namenodes on [hadoop100]
hadoop100: stopping namenode
hadoop100: stopping datanode
Stopping secondary namenodes [hadoop100]
hadoop100: stopping secondarynamenode
stopping yarn daemons
stopping resourcemanager
hadoop100: stopping nodemanager
no proxyserver to stop

6、常见问题:

(1)时间校准后仍然偏差几个小时

使用nptdate 进行时间校准后发现校准后的时间仍然偏移很多,这是因为时区的设置问题(如果是纽约时间, 则相差13个小时),修改时区的方法就是删除原来的软链。软链的位置:

ll /etc/localtime
/etc/localtime -> ../usr/share/zoneinfo/America/New_York

rm /etc/localtime

删除后时间就变成了UTC时间 - 格林威治时间,与中国时间相差8个小时

接下来只需要重新生成一个指向中国时区的软链,就可以正常显示中国时区的时间了

$ sudo ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

这样时区就没问题了

(2)没有DataNode

如果多次格式化会导致NamdeNode新生成的CID和DataNode不一致

  • 解决办法,

    • 停止集群,将DN的CID修改成和NN的CID一致,格式化NN,再启动集群
    • 建议
    • 停止集群,删除hadoop.tmp.dir下的所有内容,格式化NN,再启动集群
    • 不建议,会丢失数据,如果不怕丢失数据可以这样做

(3)MapReducer任务失败

有很多原因,主要是分析日志的信息

一般的原因是:

  • 缺少服务进程

    • 查找对应服务的日志
  • 输出目录已经存在

    • 删除已经存在的目录或者改为不存在的目录
  • Host无法解析

    • 检查/etc/hosts的映射的主机名和ip是否准确
    • 检查所有配置文件中的主机名和端口号是否正确
  • 其他的错误

    • 可以通过MR的历史日志进行定位

    • 或者通过MR任务的Yarn日志查看任务执行细节

    yarn logs -applicationId <applicationId>

Views: 114

01- 安装Centos7虚拟机

安装Centos7

1、下载

网易、阿里、搜狐等公司都有开源镜像站提供CentOS7的镜像文件下载,以阿里云镜像站为例:

Index of /centos/7/isos/x86_64/


../
0_README.txt                                       06-Nov-2020 14:32                2495
CentOS-7-x86_64-DVD-2009.iso                       04-Nov-2020 11:37          4712300544
CentOS-7-x86_64-DVD-2009.torrent                   06-Nov-2020 14:44              180308
CentOS-7-x86_64-Everything-2009.iso                02-Nov-2020 15:18         10200547328
CentOS-7-x86_64-Everything-2009.torrent            06-Nov-2020 14:44              389690
CentOS-7-x86_64-Minimal-2009.iso                   03-Nov-2020 14:55          1020264448
CentOS-7-x86_64-Minimal-2009.torrent               06-Nov-2020 14:44               39479
CentOS-7-x86_64-NetInstall-2009.iso                26-Oct-2020 16:26           602931200
CentOS-7-x86_64-NetInstall-2009.torrent            06-Nov-2020 14:44               23567
sha256sum.txt                                      04-Nov-2020 11:38                 398
sha256sum.txt.asc    

下载最小化安装版本 CentOS-7-x86_64-Minimal-2009.iso

2、配置虚拟机软件

这里使用VmwareStation15.5

为了方便,采用NAT连接方式,NAT模式的虚拟网卡名称默认为VMnet8

为了统一网段,修改虚拟机网络编辑器配置如下,将第三段修改为186

image-20210109071819453

网关也要对应修改

image-20210109071924873

3、创建虚拟机

  1. 创建虚拟机,选择典型,安装程序光盘映像文件选择前面下载的iso文件。
  2. 安装位置不要采用默认设置,最好自己指定
  3. 磁盘大小,为了便于扩展,最大容量选择50G
  4. 为了拷贝方便,选择拆分多个文件
  5. 如果宿主内存足够,虚拟机内存可设置为4096MB,但最好不要超过宿主内存的一半以上
  6. 网络适配器默认采用NAT连接

最终结果

image-20210109072813301

然后选择完成进行系统安装,在安装界面设置

  1. 本地化

    1. 安装界面语言-简体中文
    2. 日期默认亚洲上海时区
    3. 键盘采用默认配置即可
    4. 语言支持除了中文外添加English(United States)
  2. 软件

    1. 安装源 - 无需设置
    2. 软件选择 - 由于已经是最小安装,因此无需设置
  3. 系统

    1. 安装位置

      1. 选择本地标准磁盘(40G)
      2. 选择我要配置分区
        1. 创建挂载点
        2. /boot 200 MiB
        3. /swap 2048 MiB
        4. / 剩余的37.8 GiB
      3. 完成 - 接受更改
    2. KDUMP - 忽略

    3. 网络和主机名(也可以忽略,以后自行修改)

      1. 开启以太网ens33
      2. 编辑ens33网络
        1. 方法手动
        2. 添加地址
        3. IP = 192.168.186.100
        4. 子网掩码 = 255.255.255.0
        5. 网关 192.168.186.2 - 和虚拟机的NAT连接网络设置保持一致
        6. DNS = 223.5.5.5,8.8.8.8 - 前置是国内通用DNS地址,后者是谷歌的DNS地址(可能被墙)
    4. 开始安装

      1. 设置ROOT密码 - niit1234, 两次确认完成简单密码(由于是学习用的虚拟机)的设置
      2. 创建用户 - 忽略,以后可以自行创建
    5. 重启

4、网络配置

测试能否ping通百度

[root@localhost ~]# ping baidu.com
PING baidu.com (220.181.38.148) 56(84) bytes of data.
64 bytes from 220.181.38.148 (220.181.38.148): icmp_seq=1 ttl=128 time=53.5 ms
64 bytes from 220.181.38.148 (220.181.38.148): icmp_seq=2 ttl=128 time=57.5 ms
64 bytes from 220.181.38.148 (220.181.38.148): icmp_seq=3 ttl=128 time=52.5 ms
(Ctrl-C退出)

如果不能,则检查配置,其中注释处重点检查

[root@localhost ~]# vi /etc/sysconfig/network-scripts/ifcfg-ens33 

TYPE="Ethernet"
PROXY_METHOD="none"
BROWSER_ONLY="no"
BOOTPROTO="static"                            # static - 静态分配IP地址
DEFROUTE="yes"
IPV4_FAILURE_FATAL="no"
IPV6INIT="yes"
IPV6_AUTOCONF="yes"
IPV6_DEFROUTE="yes"
IPV6_FAILURE_FATAL="no"
IPV6_ADDR_GEN_MODE="stable-privacy"
NAME="ens33"
UUID="b00b9ac0-60c2-4d34-ab88-2413055463cf"
DEVICE="ens33"
ONBOOT="yes"                              # 系统启动时网络接口是否有效
IPADDR="192.168.186.100"                   # 静态IP
PREFIX="24"
GATEWAY="192.168.186.2"                        # 网关
DNS1="223.5.5.5"                          
DNS2="8.8.8.8"
IPV6_PRIVACY="no"
  1. 为了避免动态分配ip造成ip变动导致集群不稳定,一定要修改成为静态ip
  2. ONBOOT="yes" 可以开机时开启网络接口,便于联网
  3. 网关要和虚拟机的VMnet8的配置相同

修改后重启网络服务

[root@localhost ~]# service network restart
Restarting network (via systemctl):                        [  确定  ]

如果报错,则使用reboot命令重启系统

5、主机名配置

查看

[root@localhost ~]# hostname
localhost.localdomain

修改(主机名全小写,且不要有下划线)

[root@localhost ~]# hostnamectl --static set-hostname hadoop100

[root@localhost ~]# hostname
hadoop100

查看虚拟机IP

[hadoop@hadoop100 ~]$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:05:2a:0e brd ff:ff:ff:ff:ff:ff
    inet 192.168.186.100/24 brd 192.168.186.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::ac3e:51e8:9275:6fcd/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

其中ens33的 inet 192.168.186.100 即为当前虚拟机的ipv4的地址

修改虚拟机的IP和主机名映射文件

# vi /etc/hosts vi /etc/hosts

#127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
#::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

192.168.186.100 hadoop100

同时也需要修改Windows的主机映射文件

C:\Windows\System32\drivers\etc\HOSTS

# hadoop
192.168.186.100 hadoop100
192.168.186.101 hadoop101
192.168.186.102 hadoop102

其中

  1. hadoop100-hadoop102为大数据全分布式环境的主机名设置

另,新修改的主机名要重新登录终端或者重启系统后才能显示正常,如 [root@hadoop100 ~]#

6、防火墙设置

为了方便Windows或其他系统可以访问Linux虚拟机内的服务,为了方便学习的目的可以关闭虚拟机的防火墙服务(真实服务器上不要这样做)

关闭防火墙,可以避免端口被限制

[root@hadoop100 ~]# systemctl status firewalld.service
● firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled; vendor preset: enabled)
   Active: active (running) since 六 2021-01-09 08:03:31 CST; 38min ago
     Docs: man:firewalld(1)
 Main PID: 706 (firewalld)
   CGroup: /system.slice/firewalld.service
           └─706 /usr/bin/python2 -Es /usr/sbin/firewalld --nofork --nopid

1月 09 08:03:30 localhost.localdomain systemd[1]: Starting firewalld - dynamic firewall daemon...
1月 09 08:03:31 localhost.localdomain systemd[1]: Started firewalld - dynamic firewall daemon.
1月 09 08:03:32 localhost.localdomain firewalld[706]: WARNING: AllowZoneDrifting is enabled. This ...w.
Hint: Some lines were ellipsized, use -l to show in full.
[root@hadoop100 ~]# systemctl stop firewalld.service
[root@hadoop100 ~]# systemctl status firewalld.service
● firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)
   Active: inactive (dead)
     Docs: man:firewalld(1)

1月 09 08:03:30 localhost.localdomain systemd[1]: Starting firewalld - dynamic firewall daemon...
1月 09 08:03:31 localhost.localdomain systemd[1]: Started firewalld - dynamic firewall daemon.
1月 09 08:03:32 localhost.localdomain firewalld[706]: WARNING: AllowZoneDrifting is enabled. This ...w.
1月 09 08:42:23 hadoop100 systemd[1]: Stopping firewalld - dynamic firewall daemon...
1月 09 08:42:23 hadoop100 systemd[1]: Stopped firewalld - dynamic firewall daemon.
Hint: Some lines were ellipsized, use -l to show in full.

(如果是Centos6,则默认的防火墙服务名为iptables)

  1. systemctl的status可以查看现有服务的状态
  2. systemctl的stop可以临时关闭防火墙
  3. 还可以使用systemctl的disable和enable来永久禁用和启用服务,

这里为了方便禁用自动开机启动防火墙服务

[root@hadoop100 ~]# systemctl disable firewalld.service
[root@hadoop100 ~]# systemctl is-enabled firewalld.service
disabled

7、安装vim

Centos默认没有安装vim, 为了编辑时能得到高亮显示,这里安装vim,并替换原来的vi命令

# yum install vim

[root@hadoop100  ~]# vi ~/.bashrc 

# .bashrc
# User specific aliases and functions

alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
alias vi=vim

# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi

使设置生效

[root@hadoop100 ~]# source ~/.bashrc 

8、创建操作用户

root用户具有太大操作权限,实际操作时需要对不同的用户设置不同的限制,所以需要另外创建一个一般用途的用户。

[root@hadoop100 ~]# useradd hadoop
[root@hadoop100 ~]# passwd hadoop
改用户 hadoop 的密码 。
新的 密码:123123
无效的密码: 密码少于 8 个字符
重新输入新的 密码:123123
passwd:所有的身份验证令牌已经成功更新。

修改sudoer配置文件

[root@hadoop100 ~]# source ~/.bashrc 

由于前面已经设置了vim的别名为vi,这里会直接使用vim进行编辑

  1. 在vim中,键入:set nu可以显示行号

  2. 键入100G可以快速跳转到第100行位置

  3. 键入yy复制当前行,键入p拷贝到下一行

  4. 进行如下修改

    ## Next comes the main part: which users can run what software on 
    ## which machines (the sudoers file can be shared between multiple
    ## systems).
    ## Syntax:
    ##
    ##      user    MACHINE=COMMANDS
    ##
    ## The COMMANDS section may have other options added to it.
    ##
    ## Allow root to run any commands anywhere 
    root    ALL=(ALL)       ALL
    hadoop  ALL=(ALL)       NOPASSWD:ALL
    1. 第一个配置ALL=(ALL)是让hadoop用户拥有root权限
    2. 第二个配置NOPASSWD:ALL是当hadoop用户执行sudo命令时,不需要输入hadoop用户的密码

    登录新用户进行测试

    [root@hadoop100 root]$ su hadoop
    [hadoop@hadoop100 ~]$ cd ~
    [hadoop@hadoop100 ~]$ sudo yum install -y net-tools
    [hadoop@hadoop100 ~]$ ifconfig
    ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
           inet 192.168.186.100  netmask 255.255.255.0  broadcast 192.168.186.255
           inet6 fe80::ac3e:51e8:9275:6fcd  prefixlen 64  scopeid 0x20<link>
           ether 00:0c:29:05:2a:0e  txqueuelen 1000  (Ethernet)
           RX packets 1338  bytes 431899 (421.7 KiB)
           RX errors 0  dropped 0  overruns 0  frame 0
           TX packets 920  bytes 113806 (111.1 KiB)
           TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
           inet 127.0.0.1  netmask 255.0.0.0
           inet6 ::1  prefixlen 128  scopeid 0x10<host>
           loop  txqueuelen 1000  (Local Loopback)
           RX packets 32  bytes 2592 (2.5 KiB)
           RX errors 0  dropped 0  overruns 0  frame 0
           TX packets 32  bytes 2592 (2.5 KiB)
           TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    1. yum install进行软件安装是需要root权限的,因此需要加上sudo来执行
    2. 正常情况下sudo命令需要提供当前用户的密码,确认成功后才能执行命令
    3. 由于我们在/etc/sudoers为hadoop用户配置了root权限以及免sudo密码,所以无需输入密码
    4. 查看ip使用ifconfig要比ip a的方式有更好的显示和更多的选项

9、虚拟机备份

有时候虚拟机可能为因为磁盘损坏导致引导失败,建议为重要的虚拟机制作备份

  1. 可以使用VMwareStation自带的虚拟机克隆向导实现备份
  2. 拍快照
  3. 选择完整克隆
  4. 为克隆的虚拟机另起一个名字

10、远程终端连接工具

由于在VMwareStation的虚拟机界面操作十分不便,无法滚动屏幕看之前的内容,也不能粘贴复制,另外有时我们需要在虚拟机和宿主机器之间传输文件,因此这里使用NetSarang公司的Xshell和Xftp进行对虚拟机的远程ssh连接和远程sftp连接客户端。

image-20210109101251564

具体使用方法请查看官方

https://www.netsarang.com/zh/xshell/

https://www.netsarang.com/zh/xftp/

另外强烈推荐另外一款远程终端产品叫做MobaXTerm, 也是非常好用!

image-20210301005639445

[END]

Views: 82

CH-02 编程准备

为什么学习C语言

  1. 操作系统编程
    • 内存管理、服务器
  2. 操作系统设计
    • 大部分系统使用C语言实现
  3. 网络协议实现
    • 局域网、互联网数据传输
  4. 物联网和嵌入式编程
    • Linux编程
  5. 实现其他语言
    1. 解释形
      • 解析器实现大多数都是C/C++
    2. 编译型
      • 高效率编译器的实现也离不开C语言

C语言历史

为了玩游戏编写了一套操作系统

C 语言的产生,还是有一些故事的。在很久很久以前,那个时期的计算机系统还处在批处理阶段,技术不发达导致了运算速度十分缓慢,也使得程序员工作效率低下。当时他们只能在运算速度缓慢笨重的大型机器上工作,操作也十分繁琐:需要先将程序卡片装入设备,然后等一个多小时才能获取运算结果。……在知名的贝尔实验室,有一个叫 Ken Thompson 和另一个叫 Dennis M. Ritchie 的工程师,他们被共同称为“C 语言之父”。
file
他们为了在实验室角落里一台 PDP-7 小型机上写一个让自己可以不用花多少钱就可以玩的《星际旅行(Star Travel)》的游戏,用汇编语言编写了一个操作系统,并把这个系统命名成了 Unix。
file
后面又出现了B语言替代了汇编,因为B语言编写的程序无法移植到其他类型的机器上,当PDP-11出来后,为了将PDP-7上的B语言移植到PDP-11上又开发了NB语言,这就是C语言的前身,1972年NB语言改名为C语言。在1973年Dennis和Ken一起使用C语言重写了Unix系统。

file

file

后又有大神Linus

Early C

  • 1969: B created, based on BCPL, to replace PDP-7 assembler as the system programming language for Unix
  • 1971: NB ("new B") created when porting B to PDP-11
  • 1972: Language renamed to C
  • 1973: Unix re-written in C
  • 1978: The C Programming Language, 1st edition

Standard C

  • 1988: The C Programming Language, 2nd edition
  • 1989: C89, the ANSI C standard published
  • 1990: C90, the ANSI C standard accepted as ISO/IEC 9899:1990
  • 1995: C95 (ISO/IEC 9899:1990/Amd.1:1995) (online store)
  • 1999: C99 (ISO/IEC 9899:1999)
  • 2011: C11 (ISO/IEC 9899:2011) (ISO store) (ANSI store) (April 12, 2011 draft)
  • 2018: C17 (ISO/IEC 9899:2018) (ISO Store) (Final draft)
  • 2023: C23 Next major C language standard revision

环境准备

C 语言即可以在Windows、也可以在macOS(Unix内核)或者Linux(类Unix)上进行开发, 需要注意平台之间的差异, 例如Windows环境下的一些库文件和函数有些"特立独行", 除了系统的差异, 也存在编译工具的差异,例如微软平台下的宇宙第一IDE的Visual Studio与其他IDE相比就存在明显的区别。

C 语言在 Unix 上被设计出来,也被基于 Unix 的操作系统更好地支持。如果你希望更顺利地学习 C 语言,使用基于 Unix 的操作系统将会是很好的选择。同时,多数情况下你将会需要使用命令行工具来进行操作。

Windows环境配置

一般IDE会自带编译环境。你也可以选择使用自己的编译环境,一般Windows上常用的C/C++编译环境是MinGW(Minimalist GNU for Windows)。为了安装 MinGW,请访问 MinGW 的主页 ,进入 MinGW 下载页面,下载最新版本的 MinGW 安装程序,命名格式为 MinGW-.exe。

Linux环境配置

file

macOS环境配置

file

文本编辑器和IDE选择

对于程序语言的初学者来说,不要轻易地使用太复杂的IDE(integrated development environment,集成式开发环境),如:

  • Visual Studio Conmmunity(IDE)
    file

  • Visual Studio Code(IDE)
    file

  • JetBrain CLion
    file

因为IDE 会隐藏很多本来应该让你学习到的知识,如果坚持要使用 IDE,对于初学者推荐你使用 Dev C++ 或 Code::Blocks 这种相对轻量的 IDE),像VC6.0这种古老的IDE就不推荐使用了。

  • Dev-C++(IDE)
    file

  • Code Blocks(IDE)
    file

也推荐使用 Atom、Sublime、NotePad++、Gedit、Nano、Emacs、Vim 这些编辑器,其中Vim、Atom、Sublime经过适当的配置也是可以达到接近IDE的效果的。如果可能,你都可以试一试,找到你最顺手的那个。

  • Sublime
    file

  • Vim(Editor)
    file

Windows系统运行Linux

  1. 运行Linux虚拟机
    • VMwareStation/VirtualBox
    • Centos 7
  2. 运行WSL(WindowSubLinux)
    • Win10

Hello World 程序代码及说明

C语言版本

#include <stdio.h>
int main()
{
    printf("hello, world!\n");
    return 0;
}
  • #编译预处理行
  • #include文件预处理命令 - 包含文件
  • #include<stdio.h>让C语言负责标准输入输出流库的头文件包含到此处
  • main()主函数,代表程序的执行入口, 主函数有一个整数返回值
  • printf()格式化输出函数, 声明自stdio.h头文件
  • return 0;退出main()函数,向调用线程返回执行结果(返回0代表程序正常退出, 返回非0代表异常退出).

C++语言版本

C++介绍
从C++(读作 C Plus Plus)的名字看, 就知道它比标准C多出太多东西了, C几乎是C语言的超集, 但也有少量特性是C所不支持的。C++ 比 C 多了 classes、templates、exceptions 这些部分,而每个部分也有很多新增的东西。这还只是语言部分,还未谈及标准库。C 有 29 个标准库头文件,C++ 有 87 个,除了量,C++ 标准库的功能要复杂得多。是目前最难掌握也是最为复杂的语言。

我们课程学习所使用的C++只用到C++特性中最简单的部分,并且不涉及面向对象、模板、异常等复杂的部分。

编写C++的hello world程序很简单, 注意后缀使用cpp或者cc, 表示这是C++的源代码文件.

#include <iostream>
using namespace std;

int main()
{
  cout << "hello world" << endl;
  return 0;
}
  • iostream C++定义的输入输出流库, 定义了输入流对象cin和输出流对象cout对象
  • using namespace std;使用std命名空间, 命名空间用于避免命名冲突问题, std是C++自带的名称空间, 其种cout,cin和endl都位于这个名称空间下.
  • coutiosteam库中ostream类型对象,用于将<<右侧的内容输出到显示屏
  • endliostream库中定义的IO操纵符,表示换行并刷新流

GCC

GCC:GNU Compiler Collection(GUN 编译器集合),它可以编译C、C++、Java、Fortran、Pascal、Object-C、Ada等语言。

  • gcc是GCC中的GUN C Compiler(C 编译器)
  • g++是GCC中的GUN C++ Compiler(C++编译器)

gcc和g++的主要区别

  1. 对于 .c和.cpp文件,gcc分别当做c和cpp文件编译(c和cpp的语法是不一样的)
  2. 对于 .c和.cpp文件,g++则统一当做cpp文件编译
  3. 使用g++编译文件时,g++会自动链接标准库STL,而gcc不会自动链接STL

主要参数

-g - turn on debugging (so GDB gives morefriendly output)
-Wall - turns on most warnings
-O or -O2 or -O3 - turn on optimizations level 1~3
-o - name of the output file
-c - output an object file (.o)
-I - specify an includedirectory
-L - specify a libdirectory
-l - link with librarylib.a

GCC编译的4个阶段

file

  1. 预处理阶段:预处理器(cpp)

    $ gcc -E hello.c -o hello.i
    # 加上-P可以生成内容弄个更精简的文件
    $ gcc -E -P hello.c -o hello.i

    预处理阶段主要做的事情是:

    • 删注释
    • 替换宏定义
    • 替换#inlcude文件
  2. 编译阶段:编译器(ccl)

    $ gcc -S hello.i -o hello.s

    编译器将预处理的文件编译成汇编指令。

  3. 汇编阶段:汇编器(as)

    $ gcc -c hello.s -o hello.o

    汇编器将汇编指令转换为二进制目标文件。
    也可以把汇编和链接阶段合称为编译阶段,生成的.o目标文件可以使用nm命令列出所有符号,其中U表示的是未定义的符号。

    
    ➜ nm hello.o
                  U _GLOBAL_OFFSET_TABLE_
    0000000000000000  T main
                  U puts
  4. 链接阶段:链接器(ld)

    $ gcc hello.o -o hello

    也可以使用-save-tmps选项保存中间生成的临时文件,如:

    ➜ gcc -Wall -save-temps hello.c -o hello
    ➜ ls
    hello hello.c  hello.i  hello.o  hello.out  hello.s
    • -Wall 显示所有编译警告信息

如果编译成功,我们在同一个目录下可以得到一个编译后的可以执行的hello文件,可以在同一目录下使用./hello命令运行。

如果你选择了使用 IDE,你需要了解一下自己的 IDE 的编译和运行功能被设计成了什么样的菜单选项或按钮。每次先编译,确认编译通过后再运行。

file

输出流对象cout

cout 是C++中 ostream 类型的对象,该类被封装在 <iostream> 库中,该库定义的名字都在命名空间 std 中,所以 cout 全称是 std::cout

cout使用方式

  • std::cout
    std::cout << "Welcome to Tsinghua" << std::endl;
  • 使用 std 命名空间后,简写成 cout
    use namespace std;
    ......
    cout << "Welcome to Tsinghua" << endl;

file

算术运算符

C/C++支持5种常见的算术运算符(operator),分别是:

  • +
  • -
  • *
  • /
  • % 取余(取模)

除了取余运算符要求两边的操作数(operand)是整数外,其余加、减、乘、除运算要求两边操作数是实数即可。

数学函数

/*
计算 sin(20°) + cos(20°) - cos(20°) / tan(20°)
需要引入cmath库的三角函数, 参数单位为弧度
弧度与角度之间的转换公式:
弧度=角度 /180 × π
*/
#include <iostream>       // 预编译 - io流库 - 输入输出
#include <cmath>          // 预编译 - cmath库 - 三角函数
using namespace std;      // 使用命名空间

int main() {    // 主函数
    const float PI = 3.14159;
    printf("%f \n", sin(30.0 / 180 * PI));
    cout << sin(20.0 / 180 * PI) +
        cos(20.0 / 180 * PI) -
        cos(20.0 / 180 * PI) /
        tan(20.0 / 180 * PI)
        << endl;
    return 0;       // 返回0 代表程序正常结束
}

注意,上面程序30.0/180如果改成30/180则结果为0,这时因为计算时发生了隐式类型转换

其他常用数学函数

****************************************
Author: Delucia
Ver.:   0.0
Date:   2020年1月5日01:06:14
Description:
附录B - 库函数  B.1数学函数
弧度转角度 2π = 360°
正弦函数, 参数x为弧度值 - double sin (double x)
*****************************************/

#include <iostream>
#include <cmath>
#include <cstdlib>

using namespace std;

int main()
{
  // 对不同类型的 n, 计算 |n|
  cout << abs(-4294967295) << endl;
  cout << labs(-4294967296L) << endl;
  cout << fabs(-3.1415926535) << endl;

  // sin 90 = 1
  cout << sin(3.1415926/2.0) << endl;
  cout << asin(1) << endl;

  cout << cos(3.1415926535/2.0) << endl;
  cout << acos(4.48966e-011) << endl;
  cout << tan(45.0*3.1415926535/180.0) << endl;
  cout << atan(1) << endl;

  cout << exp(1) << endl;
  cout << exp(2.302585093) << endl;

  cout << log(exp(1)) << endl;
  cout << log10(10) << endl;

  cout << pow(2.0, 3.0) << endl;
  cout << sqrt(25.0) << endl;

  cout << floor(4.8) << endl;
  cout << floor(-4.8) << endl;

  return 0;
}

注释

文件头注释

//***************************************
// FileName: 2-4-1comments.cpp          *
// Author: Delucia                      *
// Date: 2020年1月4日20:13:03           *
// Description: How to use Comments     *
//***************************************

int main()
{
    return 0;
}

单行注释

// 被注释的行

多行注释

/*
被注释的行
被注释的行
/*
  • 编程初学者尽量多写注释
  • 有经验的程序员会尽量让代码达到自解释效果,只对必要的地方写上注释
  • 建议养成写注释的习惯(难)

作业

file

将上面练习改写为C++的版本,并手动编译运行.

学习资源参考

  • NIIT云课堂
  • 慕课网(imooc)
  • 网易云课堂

学习文档资源参考

  • Google/Baidu
  • StackOverFlow
  • GitHub
  • CSDN
  • 菜鸟教程
  • Cpp Reference

Views: 50