使用SQL语句完成下列导出、导入操作:
- 将/etc/passwd文件导入userdb库user表并给每条记录加编号
- 将userdb库user表中UID小于100的前10条记录导出,存为/myload/user2.txt文件
步骤一:将/etc/passwd文件导入MySQL数据库
导入后的表结构取决于/etc/passwd配置文件。若一时记不住各字段的含义,也可以查看passwd配置文件的man手册页,找到格式描述相关的说明,比如:
[root@zhangyx ~]# man 1 passwd
PASSWD(1) User utilities PASSWD(1)
NAME
passwd - update user's authentication tokens
SYNOPSIS
passwd [-k] [-l] [-u [-f]] [-d] [-e] [-n mindays]
[-x maxdays] [-w warndays] [-i inactivedays] [-S]
[--stdin] [username]
DESCRIPTION
The passwd utility is used to update user's authen‐
tication token(s).
This task is achieved through calls to the Linux-
PAM and Libuser API. Essentially, it initializes
itself as a "passwd" service with Linux-PAM and
utilizes configured password modules to authenti‐
cate and then update a user's password.
A simple entry in the global Linux-PAM configura‐
tion file for this service would be:
#
# passwd service entry that does strength checking
of
# a proposed password before updating it.
#
passwd password requisite pam_cracklib.so retry=3
passwd password required pam_unix.so use_authtok
#
Note, other module types are not required for this
application to function correctly.
1)新建userdb库、user表
以数据库用户root登入MySQL服务:
[root@zhangyx ~]# mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 6
Server version: 5.7.27-log MySQL Community Server (GPL)
Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
新建userd库,切换到userd库:
mysql> create database userd;
Query OK, 1 row affected (0.01 sec)
mysql> USE userd;
Database changed
mysql>
新建user表,字段设置及相关操作参考如下:
mysql> create table user(
-> username varchar(24) NOT NULL,
-> password varchar(48) DEFAULT 'x',
-> uid int(5) NOT NULL,
-> fullname varchar(48),
-> homedir varchar(64) NOT NULL,
-> shell varchar(24) NOT NULL
-> );
Query OK, 0 rows affected (0.02 sec)
确认user表的结构:
mysql> DESC user;
+----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| username | varchar(24) | NO | | NULL | |
| password | varchar(48) | YES | | x | |
| uid | int(5) | NO | | NULL | |
| fullname | varchar(48) | YES | | NULL | |
| homedir | varchar(64) | NO | | NULL | |
| shell | varchar(24) | NO | | NULL | |
+----------+-------------+------+-----+---------+-------+
6 rows in set (0.00 sec)
2)如果直接导入会报错。在MySQL 5.7.6版本之后,导入文件只能在secure_file_priv指定的文件夹下。
mysql> load data infile '/etc/passwd' into table user fields terminated by ':';
ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
执行show variables like '%secure%'命令显示文件目录,报错即解决:
mysql> show variables like '%secure%';
+--------------------------+-----------------------+
| Variable_name | Value |
+--------------------------+-----------------------+
| require_secure_transport | OFF |
| secure_auth | ON |
| secure_file_priv | /var/lib/mysql-files/ |
+--------------------------+-----------------------+
3 rows in set (0.00 sec)
3)执行导入操作
将/etc/passwd文件复制到/var/lib/mysql-files/目录下
[root@zhangyx ~]# cp /etc/passwd /var/lib/mysql-files //这里复制格式为cp a b (a与b之间要有空格,否则报错)
读取/var/lib/mysql-files/passwd文件内容,以“:”为分隔,导入到user表中:
mysql> load data infile '/var/lib/mysql-files/passwd' into table user fields terminated by ':';
Query OK, 23 rows affected, 23 warnings (0.01 sec)
Records: 23 Deleted: 0 Skipped: 0 Warnings: 23
注:如果这里报如下错:
ERROR 1262 (01000): Row 1 was truncated; it contained more data than there were input columns
则很可能是由于数据文件中的列数跟 MySQL 数据表字段数目没有完全匹配,并且 sql_mode 设为 strict 模式的缘故。要想在这种情况下继续导入数据到 MySQL 表中,则需要设置 MySQL sql_mode 变量。把“strict_trans_tables” 从 sql_mode 中去掉,如下:
mysql> show variables like 'sql_mode';
+---------------+-------------------------------------------------------------------------------------------------------------------------------------------+
| Variable_name | Value |
+---------------+-------------------------------------------------------------------------------------------------------------------------------------------+
| sql_mode | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+---------------+-------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
设置 MySQL sql_mode,使其不包含 “strict_trans_tables” mode
mysql> set sql_mode='';
Query OK, 0 rows affected, 1 warning (0.00 sec)
这样报错问题就解决了
上述操作中省略了行分隔 LINES TERMINATED BY ‘\n’,因为这是默认的情况(每行一条原始记录),除非需要以其他字符分割行,才需要用到这个。
比如,以下操作指定了行分隔为’\n’,将/var/lib/mysql-files/passwd文件的内容导入另一个表user2,最终user2表的内容与user的内容是一样的。
mysql> CREATE TABLE user2 //参照user表结构建立新表
-> SELECT * FROM user WHERE FALSE;
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> LOAD DATA INFILE '/var/lib/mysql-files/passwd' //导入时指定行分隔
-> INTO TABLE user2
-> FIELDS TERMINATED BY ':'
-> LINES TERMINATED BY '\n';
Query OK, 23 rows affected, 23 warnings (0.01 sec)
Records: 23 Deleted: 0 Skipped: 0 Warnings: 23
4)确认导入结果
分别统计user、user2表内的记录个数:
mysql> select count(*) from user;
+----------+
| count(*) |
+----------+
| 23 | //user表有23条记录
+----------+
1 row in set (0.00 sec)
mysql> select count(*) from user2;
+----------+
| count(*) |
+----------+
| 23 | //user2表也有23条记录
+----------+
1 row in set (0.00 sec)
查看user表的前10条记录,列出用户名、UID、GID、宿主目录、登录Shell:
mysql> select username,uid,homedir,shell from user limit 10;
+----------+-----+----------+-----------------+
| username | uid | homedir | shell |
+----------+-----+----------+-----------------+
| root | 0 | root | /root |
| bin | 1 | bin | /bin |
| daemon | 2 | daemon | /sbin |
| adm | 3 | adm | /var/adm |
| lp | 4 | lp | /var/spool/lpd |
| sync | 5 | sync | /sbin |
| shutdown | 6 | shutdown | /sbin |
| halt | 7 | halt | /sbin |
| mail | 8 | mail | /var/spool/mail |
| operator | 11 | operator | /root |
+----------+-----+----------+-----------------+
10 rows in set (0.01 sec)
查看user2表的前10条记录,同样列出用户名、UID、GID、宿主目录、登录Shell:
mysql> select username,uid,homedir,shell from user2 limit 10;
+----------+-----+----------+-----------------+
| username | uid | homedir | shell |
+----------+-----+----------+-----------------+
| root | 0 | root | /root |
| bin | 1 | bin | /bin |
| daemon | 2 | daemon | /sbin |
| adm | 3 | adm | /var/adm |
| lp | 4 | lp | /var/spool/lpd |
| sync | 5 | sync | /sbin |
| shutdown | 6 | shutdown | /sbin |
| halt | 7 | halt | /sbin |
| mail | 8 | mail | /var/spool/mail |
| operator | 11 | operator | /root |
+----------+-----+----------+-----------------+
10 rows in set (0.00 sec)
步骤二:为user表中的每条记录添加自动编号
这个只要修改user表结构,添加一个自增字段即可。
比如,添加一个名为sn的序号列,作为user表的第一个字段:
1)添加自增主键字段sn
mysql> alter table user
-> add sn int(4) auto_increment primary key first;
Query OK, 0 rows affected (0.08 sec)
Records: 0 Duplicates: 0 Warnings: 0
2)验证自动编号结果
查看user表的前10条记录,列出序号、用户名、UID、GID、宿主目录:
mysql> select sn username,uid,homedir,shell from user limit 10;
+----------+-----+----------+-----------------+
| username | uid | homedir | shell |
+----------+-----+----------+-----------------+
| 1 | 0 | root | /root |
| 2 | 1 | bin | /bin |
| 3 | 2 | daemon | /sbin |
| 4 | 3 | adm | /var/adm |
| 5 | 4 | lp | /var/spool/lpd |
| 6 | 5 | sync | /sbin |
| 7 | 6 | shutdown | /sbin |
| 8 | 7 | halt | /sbin |
| 9 | 8 | mail | /var/spool/mail |
| 10 | 11 | operator | /root |
+----------+-----+----------+-----------------+
步骤三:从MySQL数据库中导出查询结果
以将userdb库user表中UID小于100的前10条记录导出为/myload/user2.txt文件为例。
1)确认存放导出数据的文件夹
[root@zhangyx ~]# ls -ld /var/lib/mysql-files/
drwxr-x--- 2 mysql mysql 4096 Jul 26 15:13 /var/lib/mysql-files/
2)修改目录及查看修改结果
[root@zhangyx ~]# mkdir /myloads; chown mysql /myload
[root@zhangyx ~]# vim /etc/my.cnf
[mysqld]
secure_file_priv="/myloads"
[root@zhangyx ~]# systemctl restart mysqld
mysql> show variables like "secure_file_priv";
+------------------+-----------+
| Variable_name | Value |
+------------------+-----------+
| secure_file_priv | /myloads/ |
+------------------+-----------+
1 row in set (0.00 sec)
2)导出user表中UID小于100的前10条记录
如果以默认的’\n’ 为行分隔,导出操作同样可不指定LINES TERMINATED BY:
mysql> SELECT * FROM userdb.user WHERE uid<100
-> INTO OUTFILE '/myload/user2.txt'
-> FIELDS TERMINATED BY ':';
Query OK, 24 rows affected (0.00 sec)
3)确认导出结果
返回到Shell命令行,查看/myload/user2.txt文件的行数:
[root@zhangyx ~]# wc -l /myload/user2.txt
24 /myload/user2.txt
查看/myload/user2.txt文件的最后10行内容:
[root@zhangyx ~]# tail /myload/user2.txt
19:avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin
24:rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
25:rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
28:radvd:x:75:75:radvd user:/:/sbin/nologin
29:ntp:x:38:38::/etc/ntp:/sbin/nologin
33:gdm:x:42:42::/var/lib/gdm:/sbin/nologin
35:postfix:x:89:89::/var/spool/postfix:/sbin/nologin
36:sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
37:tcpdump:x:72:72::/:/sbin/nologin
39:mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/false