从 java 代码设置日期和时间时出现问题
Problem in setting date and time from java code
我正在尝试使用 Java 从远程系统设置 linux 系统的日期和时间。为此,我创建了一个服务器来接受来自远程系统的时间:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class Set_date_n_time {
public static void main(String[] args) throws IOException, InterruptedException {
// TODO Auto-generated method stub
String date_time = new String();
//@SuppressWarnings("resource")
ServerSocket s1 = new ServerSocket(7105);
System.out.println("server started");
while (true) {
Socket sckt = s1.accept();
InputStream input = sckt.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
date_time = reader.readLine();
String command="sudo date -s "+"\""+date_time+"\"";
Process p;
try {
p = Runtime.getRuntime().exec(command);
p.waitFor();
System.out.println ("date set");
p.destroy();
} catch (Exception e) {}
}
}
}
以及将从中复制时间的远程系统为:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Fix_my_Date {
public static void main(String args[]) throws IOException {
String addr_list=args[0];
String[] hostList = readAddressList(addr_list);
for(int i=0; i<hostList.length;i++) {
setDate(hostList[i]);
}
}
//@SuppressWarnings("resource")
private static void setDate(String address) throws IOException {
{
Scanner sc = new Scanner(System.in);
Socket s = null;
String date =new String();
String time = new String();
try {
s = new Socket(address, 7105);
System.out.println("connection to "+address+" done");
Process p, p1;
try {
p = Runtime.getRuntime().exec("date +%Y%m%d");
BufferedReader br = new BufferedReader(
new InputStreamReader(p.getInputStream()));
date = br.readLine();
br.close();
p.waitFor();
p.destroy();
p1 = Runtime.getRuntime().exec("date +%H:%M:%S");
BufferedReader br1 = new BufferedReader(
new InputStreamReader(p1.getInputStream()));
time = br1.readLine();
br1.close();
p1.waitFor();
p1.destroy();
PrintStream pr = new PrintStream(s.getOutputStream());
pr.print(date+" "+time+"");
sc.close();
s.close();
} catch (Exception e) {
System.out.println("Problem Setting date and time");
}
//s.close();
} catch (Exception e) {
System.out.println("Couldn't connect to: "+address+"");
sc.close();
//s.close();
}
}
return;
}
private static String[] readAddressList(String addr_list) throws IOException {
FileReader fileReader = new FileReader(addr_list);
BufferedReader bufferedReader = new BufferedReader(fileReader);
List<String> lines = new ArrayList<String>();
String line = null;
while ((line = bufferedReader.readLine()) != null)
{
lines.add(line);
}
bufferedReader.close();
System.out.println("Loaded the host list");
return lines.toArray(new String[lines.size()]);
}
}
但是服务器代码没有设置时间。我的错误在哪里?
您要在虚拟机上设置时间吗?如果是这种情况,它可能被设置为与覆盖您的 date -s 命令的主机同步。
我无法让它(还)与 Runtime.exec() 一起工作,但它与 ProcessBuilder 完美配合。这是:
package set_date_n_time;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class Set_date_n_time {
public static void main(String[] args) throws IOException, InterruptedException {
// TODO Auto-generated method stub
String date_time = new String();
//@SuppressWarnings("resource")
ServerSocket s1 = new ServerSocket(7105);
System.out.println("server started");
while (true) {
Socket sckt = s1.accept();
InputStream input = sckt.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
date_time = reader.readLine();
ProcessBuilder builder = new ProcessBuilder("date", "--set=" + date_time + "");
final Process p = builder.start();
p.waitFor();
p.destroy();
}
}
}
显然你必须 运行 作为 root 并确保你 运行
sudo systemctl stop systemd-timesyncd.service
或类似的东西以确保系统不会覆盖您的日期修复。
如果您需要或更喜欢使用 Runtime.exec() 那么(不要问我为什么)只需更改:
String command = "sudo date -s " + "\"" + date_time + "\"";
至
String[] command = new String[]{"sudo", "date", "-s", date_time};
在 class Set_date_n_time.
替换为:
} catch (Exception e) {}
有了这个:
} catch (Exception e) {
throw new IllegalStateException("Unexpected exception", e);
}
作为 Ole V.V。也就是说,您代码中的空 catch 块几乎肯定会丢弃您关心的真正失败。我猜想要么 sudo
拒绝了呼叫,要么命令本身格式错误。异常会告诉你到底出了什么问题。
如果你发现有异常被抛出,你真的想忽略,单独处理它们,但你几乎不应该 catch (Exception e)
并丢弃异常.
使用 ProcessBuilder
代替 Runtime.exec()
也是一个好主意。这是一个更强大和灵活的 API 用于与子流程交互。特别是,从不 使用Runtime.exec(String)
;虽然它适用于简单的命令,但它 而不是 和 shell,并且对于带有特殊字符(如引号或空格)的命令,它会以令人惊讶的方式失败。
例如:
p = new ProcessBuilder("sudo", "date", "-s", date_time).start();
我、你和许多其他人犯的错误还在于(除了此处的其他有用答案之外)你没有阅读标准输出和标准错误,如果你的命令产生任何输出或错误,它会阻止,因为那里没有可以写入的缓冲区,您可以使用 strace
.
观察
这可以通过此处所述的额外线程来解决:https://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html
如果您使用 sudo,它可能会失败,具体取决于 sudo 设置,如果它不允许没有终端的 sudo(要求),请参阅更多信息,例如:https://bugzilla.redhat.com/show_bug.cgi?id=1196451
我正在尝试使用 Java 从远程系统设置 linux 系统的日期和时间。为此,我创建了一个服务器来接受来自远程系统的时间:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class Set_date_n_time {
public static void main(String[] args) throws IOException, InterruptedException {
// TODO Auto-generated method stub
String date_time = new String();
//@SuppressWarnings("resource")
ServerSocket s1 = new ServerSocket(7105);
System.out.println("server started");
while (true) {
Socket sckt = s1.accept();
InputStream input = sckt.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
date_time = reader.readLine();
String command="sudo date -s "+"\""+date_time+"\"";
Process p;
try {
p = Runtime.getRuntime().exec(command);
p.waitFor();
System.out.println ("date set");
p.destroy();
} catch (Exception e) {}
}
}
}
以及将从中复制时间的远程系统为:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Fix_my_Date {
public static void main(String args[]) throws IOException {
String addr_list=args[0];
String[] hostList = readAddressList(addr_list);
for(int i=0; i<hostList.length;i++) {
setDate(hostList[i]);
}
}
//@SuppressWarnings("resource")
private static void setDate(String address) throws IOException {
{
Scanner sc = new Scanner(System.in);
Socket s = null;
String date =new String();
String time = new String();
try {
s = new Socket(address, 7105);
System.out.println("connection to "+address+" done");
Process p, p1;
try {
p = Runtime.getRuntime().exec("date +%Y%m%d");
BufferedReader br = new BufferedReader(
new InputStreamReader(p.getInputStream()));
date = br.readLine();
br.close();
p.waitFor();
p.destroy();
p1 = Runtime.getRuntime().exec("date +%H:%M:%S");
BufferedReader br1 = new BufferedReader(
new InputStreamReader(p1.getInputStream()));
time = br1.readLine();
br1.close();
p1.waitFor();
p1.destroy();
PrintStream pr = new PrintStream(s.getOutputStream());
pr.print(date+" "+time+"");
sc.close();
s.close();
} catch (Exception e) {
System.out.println("Problem Setting date and time");
}
//s.close();
} catch (Exception e) {
System.out.println("Couldn't connect to: "+address+"");
sc.close();
//s.close();
}
}
return;
}
private static String[] readAddressList(String addr_list) throws IOException {
FileReader fileReader = new FileReader(addr_list);
BufferedReader bufferedReader = new BufferedReader(fileReader);
List<String> lines = new ArrayList<String>();
String line = null;
while ((line = bufferedReader.readLine()) != null)
{
lines.add(line);
}
bufferedReader.close();
System.out.println("Loaded the host list");
return lines.toArray(new String[lines.size()]);
}
}
但是服务器代码没有设置时间。我的错误在哪里?
您要在虚拟机上设置时间吗?如果是这种情况,它可能被设置为与覆盖您的 date -s 命令的主机同步。
我无法让它(还)与 Runtime.exec() 一起工作,但它与 ProcessBuilder 完美配合。这是:
package set_date_n_time;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class Set_date_n_time {
public static void main(String[] args) throws IOException, InterruptedException {
// TODO Auto-generated method stub
String date_time = new String();
//@SuppressWarnings("resource")
ServerSocket s1 = new ServerSocket(7105);
System.out.println("server started");
while (true) {
Socket sckt = s1.accept();
InputStream input = sckt.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input));
date_time = reader.readLine();
ProcessBuilder builder = new ProcessBuilder("date", "--set=" + date_time + "");
final Process p = builder.start();
p.waitFor();
p.destroy();
}
}
}
显然你必须 运行 作为 root 并确保你 运行
sudo systemctl stop systemd-timesyncd.service
或类似的东西以确保系统不会覆盖您的日期修复。
如果您需要或更喜欢使用 Runtime.exec() 那么(不要问我为什么)只需更改:
String command = "sudo date -s " + "\"" + date_time + "\"";
至
String[] command = new String[]{"sudo", "date", "-s", date_time};
在 class Set_date_n_time.
替换为:
} catch (Exception e) {}
有了这个:
} catch (Exception e) {
throw new IllegalStateException("Unexpected exception", e);
}
作为 Ole V.V。也就是说,您代码中的空 catch 块几乎肯定会丢弃您关心的真正失败。我猜想要么 sudo
拒绝了呼叫,要么命令本身格式错误。异常会告诉你到底出了什么问题。
如果你发现有异常被抛出,你真的想忽略,单独处理它们,但你几乎不应该 catch (Exception e)
并丢弃异常.
使用 ProcessBuilder
代替 Runtime.exec()
也是一个好主意。这是一个更强大和灵活的 API 用于与子流程交互。特别是,从不 使用Runtime.exec(String)
;虽然它适用于简单的命令,但它 而不是 和 shell,并且对于带有特殊字符(如引号或空格)的命令,它会以令人惊讶的方式失败。
例如:
p = new ProcessBuilder("sudo", "date", "-s", date_time).start();
我、你和许多其他人犯的错误还在于(除了此处的其他有用答案之外)你没有阅读标准输出和标准错误,如果你的命令产生任何输出或错误,它会阻止,因为那里没有可以写入的缓冲区,您可以使用 strace
.
这可以通过此处所述的额外线程来解决:https://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html
如果您使用 sudo,它可能会失败,具体取决于 sudo 设置,如果它不允许没有终端的 sudo(要求),请参阅更多信息,例如:https://bugzilla.redhat.com/show_bug.cgi?id=1196451