在 Linux 和 Windows 上使用 Java 处理 SymbolicLink 的一些事情
java.nio.file.Files 存在系列处理 “SymbolicLink” 的功能,实测可以支持 Linux 上的 “符号链接”,以及 Windows (NTFS 文件系统) 的 “NTFS 符号链接”(在 XP 中或称为 Junction)。
关于符号链接:
- Linux链接分两种,一种被称为硬链接(Hard Link),另一种被称为符号链接(Symbolic Link)。默认情况下,ln 命令产生硬链接,ln -s 可以用于创建符号链接;
- 在 Win7 之后, Windows 提供了 mklink 命令,用于创建符号链接;
Windows 2000 - Windows XP 可以通过安装 junction 命令实现此功能,Junction 属于 Windows Sysinternals 软件包的一部分,目前可以在 https://docs.microsoft.com/en-us/sysinternals/downloads/junction 下载。
JDK 包含的相关 API 包括:
- public static Path createSymbolicLink(Path link, Path target, FileAttribute<?>... attrs) throws IOException) 此方法用于创建符号链接(另外有一个 createLink 方法用于创建硬链接,通常很少使用);
- public static boolean isSymbolicLink(Path path) 用于判断是否符号链接;
- 注意此方法在 Windows 无法发挥实际作用(对于 mklink 或者 java.nio.file.Files#createSymbolicLink创建的 NTFS 符号链接,此方法无法识别,总是返回 false);
- 在 https://stackoverflow.com/a/29699473 找到一个方法,可以作为 Windows 上判断是否符号链接的补充,大致的代码如下(语言:Mozilla Rhino JavaScript):
if (os.isWindows){ var p = java.nio.file.Paths.get(file.toURI()); result = (p.compareTo(p.toRealPath()) != 0); }else{ result = Packages.org.apache.commons.io.FileUtils.isSymlink(file); }
- public static Path readSymbolicLink(Path link) throws IOException 读取符号链接信息,常用于获得符号链接实际指向的目标地址:
var _path = java.nio.file.Paths.get(link.toURI()); var _target = java.nio.file.Files.readSymbolicLink(_path); _target.toFile().getPath() //获得 java.io.File 对象 “link” 的链接目标地址
在 Windows 上创建符号链接的权限要求:
- 在 Windows 上,系统默认的安全限制禁止非管理员权限的程序创建符号链接,在执行 createSymbolicLink 时会出现类似如下错误:
java.nio.file.Files.createSymbolicLink 客户端没有所需的特权
- 以 Windows 10 为例,可以在 本地安全策略 中进行设置:
关于 java.io.File#getCanonicalPath():
- 在 Linux 下,对于 Symbolic Link,getCanonicalPath() 将会返回链接指向的目标地址,而不是链接字面上的路径,所以合理的获取 File 对象的 CanonicalPath 的方法大致如下:
if ( Packages.org.apache.commons.io.FileUtils.isSymlink(file) ){ return java.nio.file.Paths.get(file.toURI()).normalize().toFile().getAbsolutePath(); }else{ return file.getCanonicalPath()+""; //Force convert to javascript string }
ubuntu 上安装 MySQL 5.7 后对 root 用户的处理
在 Ubuntu 18.04(Ubuntu 16.04 应该也是一样)上通过命令 sudo apt-get install mysql-server 安装 MySQL 5.7 数据库服务器的过程中,没有询问输入密码,安装完成后只能通过 sudo mysql -u root 登录到 MySQL 服务器(不用输入 MySQL 的 root 密码),而使用普通 Linux 帐号则无法登录;
按照网上的资料(参考 https://www.jianshu.com/p/4ca115648939 和 http://www.phpbug.cn/archives/621.html ),解决方案如下:
- First, connect in sudo mysql
sudo mysql -u root
- Check your accounts present in your db
mysql> SELECT User,Host FROM mysql.user;
+------------------+-----------+ | User | Host | +------------------+-----------+ | admin | localhost | | debian-sys-maint | localhost | | magento_user | localhost | | mysql.sys | localhost | | root | localhost | +------------------+-----------+
- Delete current root@localhost account
mysql> DROP USER 'root'@'localhost';
- Recreate your user
mysql> CREATE USER 'root'@'%' IDENTIFIED BY '';
- Give permissions to your user (don’t forget to flush privileges)
mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%'; mysql> FLUSH PRIVILEGES;
但是上述的操作其实会带来一个副作用,就是 在给新建的其他用户赋权限的时候会出现 mysql grant 命令错误:ERROR 1044 (42000): Access denied for 'root' With All Privileges,解决方法如下( 参考 http://www.cnblogs.com/xiaoerlang/p/4538746.html 和 https://stackoverflow.com/questions/21714869/error-1044-42000-access-denied-for-root-with-all-privileges ):
- 确认 root@localhost 是否已被赋予的权限 Grant_priv:
mysql> SELECT host,user,password,Grant_priv,Super_priv FROM mysql.user;
+-----------+------------------+-------------------------------------------+------------+------------+ | host | user | password | Grant_priv | Super_priv | +-----------+------------------+-------------------------------------------+------------+------------+ | localhost | root | ***************************************** | N | Y | | localhost | debian-sys-maint | ***************************************** | Y | Y | | localhost | staging | ***************************************** | N | N | +-----------+------------------+-------------------------------------------+------------+------------+
- 如果 root@localhost 的 Grant_priv是 N,则设为 Y:
mysql> UPDATE mysql.user SET Grant_priv='Y', Super_priv='Y' WHERE User='root'; mysql> FLUSH PRIVILEGES; mysql> GRANT ALL ON *.* TO 'root'@'localhost';
- 重新登录 MySQL,即可解决。