diff --git a/man/networkctl.xml b/man/networkctl.xml
index 5e2126ff218..e47cf5895cf 100644
--- a/man/networkctl.xml
+++ b/man/networkctl.xml
@@ -448,6 +448,9 @@ s - Service VLAN, m - Two-port MAC Relay (TPMR)
systemd.link5
for more information.
+ If is specified, the new content will be read from standard input.
+ In this mode, the old content of the file is discarded.
+
@@ -608,6 +611,23 @@ s - Service VLAN, m - Two-port MAC Relay (TPMR)
+
+
+
+
+ When used with edit, the contents of the file will be read from standard
+ input and the editor will not be launched. In this mode, the old contents of the file are
+ automatically replaced. This is useful to "edit" configuration from scripts, especially so that
+ drop-in directories are created and populated in one go.
+
+ Multiple drop-ins may be "edited" in this mode with , and
+ the same contents will be written to all of them. Otherwise exactly one main configuration file
+ is expected.
+
+
+
+
+
diff --git a/src/network/networkctl-config-file.c b/src/network/networkctl-config-file.c
index 216e9d49543..1aa03619b72 100644
--- a/src/network/networkctl-config-file.c
+++ b/src/network/networkctl-config-file.c
@@ -396,23 +396,30 @@ static int reload_daemons(ReloadFlags flags) {
}
int verb_edit(int argc, char *argv[], void *userdata) {
+ char **args = ASSERT_PTR(strv_skip(argv, 1));
_cleanup_(edit_file_context_done) EditFileContext context = {
.marker_start = DROPIN_MARKER_START,
.marker_end = DROPIN_MARKER_END,
.remove_parent = !!arg_drop_in,
+ .stdin = arg_stdin,
};
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
ReloadFlags reload = 0;
int r;
- if (!on_tty())
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot edit network config files if not on a tty.");
+ if (!on_tty() && !arg_stdin)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot edit network config files interactively if not on a tty.");
+
+ /* Duplicating main configs makes no sense. This also mimics the behavior of systemctl. */
+ if (arg_stdin && !arg_drop_in && strv_length(args) != 1)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "When 'edit --stdin' without '--drop-in=', exactly one config file for editing must be specified.");
r = mac_selinux_init();
if (r < 0)
return r;
- STRV_FOREACH(name, strv_skip(argv, 1)) {
+ STRV_FOREACH(name, args) {
_cleanup_strv_free_ char **dropins = NULL;
_cleanup_free_ char *path = NULL;
const char *link_config;
diff --git a/src/network/networkctl.c b/src/network/networkctl.c
index b51c7aa7e59..6c96a84c46b 100644
--- a/src/network/networkctl.c
+++ b/src/network/networkctl.c
@@ -91,6 +91,7 @@ bool arg_all = false;
bool arg_stats = false;
bool arg_full = false;
bool arg_runtime = false;
+bool arg_stdin = false;
unsigned arg_lines = 10;
char *arg_drop_in = NULL;
sd_json_format_flags_t arg_json_format_flags = SD_JSON_FORMAT_OFF;
@@ -3025,6 +3026,7 @@ static int help(void) {
" after editing network config\n"
" --drop-in=NAME Edit specified drop-in instead of main config file\n"
" --runtime Edit runtime config files\n"
+ " --stdin Read new contents of edited file from stdin\n"
"\nSee the %s for details.\n",
program_invocation_short_name,
ansi_highlight(),
@@ -3043,6 +3045,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_NO_RELOAD,
ARG_DROP_IN,
ARG_RUNTIME,
+ ARG_STDIN,
};
static const struct option options[] = {
@@ -3058,6 +3061,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "no-reload", no_argument, NULL, ARG_NO_RELOAD },
{ "drop-in", required_argument, NULL, ARG_DROP_IN },
{ "runtime", no_argument, NULL, ARG_RUNTIME },
+ { "stdin", no_argument, NULL, ARG_STDIN },
{}
};
@@ -3092,6 +3096,10 @@ static int parse_argv(int argc, char *argv[]) {
arg_runtime = true;
break;
+ case ARG_STDIN:
+ arg_stdin = true;
+ break;
+
case ARG_DROP_IN:
if (isempty(optarg))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Empty drop-in file name.");
diff --git a/src/network/networkctl.h b/src/network/networkctl.h
index 1765a8f83df..d44ee8173e0 100644
--- a/src/network/networkctl.h
+++ b/src/network/networkctl.h
@@ -15,6 +15,7 @@ extern bool arg_all;
extern bool arg_stats;
extern bool arg_full;
extern bool arg_runtime;
+extern bool arg_stdin;
extern unsigned arg_lines;
extern char *arg_drop_in;
extern sd_json_format_flags_t arg_json_format_flags;
diff --git a/src/systemctl/systemctl-edit.c b/src/systemctl/systemctl-edit.c
index 15398f83646..b7bd3851fd0 100644
--- a/src/systemctl/systemctl-edit.c
+++ b/src/systemctl/systemctl-edit.c
@@ -323,7 +323,7 @@ int verb_edit(int argc, char *argv[], void *userdata) {
int r;
if (!on_tty() && !arg_stdin)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot edit units if not on a tty.");
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot edit units interactively if not on a tty.");
if (arg_transport != BUS_TRANSPORT_LOCAL)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot edit units remotely.");
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 1e36455cf21..912c1d83017 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -347,7 +347,7 @@ static int systemctl_help(void) {
" --drop-in=NAME Edit unit files using the specified drop-in file name\n"
" --when=TIME Schedule halt/power-off/reboot/kexec action after\n"
" a certain timestamp\n"
- " --stdin Read contents of edited file from stdin\n"
+ " --stdin Read new contents of edited file from stdin\n"
"\nSee the %2$s for details.\n",
program_invocation_short_name,
link,
diff --git a/test/units/TEST-74-AUX-UTILS.networkctl.sh b/test/units/TEST-74-AUX-UTILS.networkctl.sh
index 3e333a2eabe..8c62de9155a 100755
--- a/test/units/TEST-74-AUX-UTILS.networkctl.sh
+++ b/test/units/TEST-74-AUX-UTILS.networkctl.sh
@@ -11,7 +11,7 @@ at_exit() {
systemctl stop systemd-networkd
if [[ -v NETWORK_NAME && -v NETDEV_NAME && -v LINK_NAME ]]; then
- rm -fvr {/usr/lib,/etc,/run}/systemd/network/"$NETWORK_NAME" "/usr/lib/systemd/network/$NETDEV_NAME" \
+ rm -fvr {/usr/lib,/etc,/run}/systemd/network/"$NETWORK_NAME" "/run/lib/systemd/network/$NETDEV_NAME" \
{/usr/lib,/etc}/systemd/network/"$LINK_NAME" "/etc/systemd/network/${NETWORK_NAME}.d" \
"new" "+4"
fi
@@ -75,13 +75,14 @@ cmp "+4" "/etc/systemd/network/${NETWORK_NAME}.d/test.conf"
networkctl cat "$NETWORK_NAME" | grep '^# ' |
cmp - <(printf '%s\n' "# /etc/systemd/network/$NETWORK_NAME" "# /etc/systemd/network/${NETWORK_NAME}.d/test.conf")
-cat >"/usr/lib/systemd/network/$NETDEV_NAME" <"/usr/lib/systemd/network/$LINK_NAME" <