rtems-proxy 0.5.2__tar.gz → 0.6.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/PKG-INFO +1 -1
  2. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/src/rtems_proxy/__main__.py +23 -10
  3. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/src/rtems_proxy/_version.py +2 -2
  4. rtems_proxy-0.6.1/src/rtems_proxy/copy.py +61 -0
  5. rtems_proxy-0.6.1/src/rtems_proxy/rsync.sh.jinja +53 -0
  6. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/src/rtems_proxy/telnet.py +22 -17
  7. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/src/rtems_proxy.egg-info/PKG-INFO +1 -1
  8. rtems_proxy-0.5.2/src/rtems_proxy/copy.py +0 -53
  9. rtems_proxy-0.5.2/src/rtems_proxy/rsync.sh.jinja +0 -30
  10. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/.copier-answers.yml +0 -0
  11. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/.devcontainer/devcontainer.json +0 -0
  12. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/.github/CONTRIBUTING.md +0 -0
  13. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  14. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/.github/ISSUE_TEMPLATE/issue.md +0 -0
  15. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +0 -0
  16. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/.github/actions/install_requirements/action.yml +0 -0
  17. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/.github/dependabot.yml +0 -0
  18. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/.github/pages/index.html +0 -0
  19. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/.github/pages/make_switcher.py +0 -0
  20. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/.github/workflows/_check.yml +0 -0
  21. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/.github/workflows/_dist.yml +0 -0
  22. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/.github/workflows/_pypi.yml +0 -0
  23. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/.github/workflows/_release.yml +0 -0
  24. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/.github/workflows/_test.yml +0 -0
  25. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/.github/workflows/_tox.yml +0 -0
  26. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/.github/workflows/ci.yml +0 -0
  27. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/.gitignore +0 -0
  28. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/.pre-commit-config.yaml +0 -0
  29. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/.vscode/extensions.json +0 -0
  30. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/.vscode/launch.json +0 -0
  31. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/.vscode/settings.json +0 -0
  32. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/.vscode/tasks.json +0 -0
  33. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/Dockerfile +0 -0
  34. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/LICENSE +0 -0
  35. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/README.md +0 -0
  36. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/proxy-start.sh +0 -0
  37. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/pyproject.toml +0 -0
  38. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/requirements.txt +0 -0
  39. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/setup.cfg +0 -0
  40. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/src/rtems_proxy/__init__.py +0 -0
  41. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/src/rtems_proxy/globals.py +0 -0
  42. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/src/rtems_proxy/utils.py +0 -0
  43. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/src/rtems_proxy.egg-info/SOURCES.txt +0 -0
  44. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/src/rtems_proxy.egg-info/dependency_links.txt +0 -0
  45. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/src/rtems_proxy.egg-info/entry_points.txt +0 -0
  46. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/src/rtems_proxy.egg-info/requires.txt +0 -0
  47. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/src/rtems_proxy.egg-info/top_level.txt +0 -0
  48. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/tests/conftest.py +0 -0
  49. {rtems_proxy-0.5.2 → rtems_proxy-0.6.1}/tests/test_cli.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: rtems-proxy
3
- Version: 0.5.2
3
+ Version: 0.6.1
4
4
  Summary: Support for a K8S proxy container in controlling and monitoring RTEMS EPICS IOCs
5
5
  Author-email: Giles Knap <giles.knap@diamond.ac.uk>
6
6
  License: Apache License
@@ -7,7 +7,7 @@ from ruamel.yaml import YAML
7
7
  from . import __version__
8
8
  from .copy import copy_rtems
9
9
  from .globals import GLOBALS
10
- from .telnet import ioc_connect
10
+ from .telnet import ioc_connect, report
11
11
 
12
12
  __all__ = ["main"]
13
13
 
@@ -40,6 +40,9 @@ def start(
40
40
  copy: bool = typer.Option(
41
41
  True, "--copy/--no-copy", help="copy binaries before connecting"
42
42
  ),
43
+ connect: bool = typer.Option(
44
+ True, "--connect/--no-connect", help="connect to the IOC console"
45
+ ),
43
46
  reboot: bool = typer.Option(
44
47
  True, "--reboot/--no-reboot", help="reboot the IOC first"
45
48
  ),
@@ -55,16 +58,21 @@ def start(
55
58
  it detects that EPICS_HOST_ARCH==RTEMS-beatnik
56
59
 
57
60
  args:
58
- copy: Copy the RTEMS binaries to the IOCs TFTP and NFS directories first
59
- reboot: Reboot the IOC once the binaries are copied and the connection is made
61
+ copy: Copy the RTEMS binaries to the IOCs TFTP and NFS directories first
62
+ connect: Connect to the IOC console after rebooting
63
+ reboot: Reboot the IOC once the binaries are copied and the connection is
64
+ made. Ignored if connect is False.
60
65
  """
61
- print(
66
+ report(
62
67
  f"Remote control startup of RTEMS IOC {GLOBALS.IOC_NAME}"
63
68
  f" at {GLOBALS.RTEMS_IOC_IP}"
64
69
  )
65
70
  if copy:
66
71
  copy_rtems()
67
- ioc_connect(GLOBALS.RTEMS_CONSOLE, reboot=reboot)
72
+ if connect:
73
+ ioc_connect(GLOBALS.RTEMS_CONSOLE, reboot=reboot)
74
+ else:
75
+ report("IOC console connection disabled. ")
68
76
 
69
77
 
70
78
  @cli.command()
@@ -91,7 +99,7 @@ def dev(
91
99
 
92
100
  ioc_path = ioc_repo / "services" / ioc_name
93
101
 
94
- values = ioc_repo / "helm/shared/values.yaml"
102
+ values = ioc_repo / "services" / "values.yaml"
95
103
  if not values.exists():
96
104
  typer.echo(f"Global settings file {values} not found. Exiting")
97
105
  raise typer.Exit(1)
@@ -106,20 +114,25 @@ def dev(
106
114
  with open(values) as fp:
107
115
  yaml = YAML(typ="safe").load(fp)
108
116
  try:
109
- ioc_group = yaml["ioc-instance"]["ioc_group"]
117
+ ioc_group = yaml["global"]["ioc_group"]
118
+ except KeyError:
119
+ typer.echo(f"{values} global.ioc_group key missing")
120
+ raise typer.Exit(1) from None
121
+ try:
122
+ ioc_group = yaml["global"]["ioc_group"]
110
123
  for item in yaml["ioc-instance"]["globalEnv"]:
111
124
  env_vars[item["name"]] = item["value"]
112
125
  except KeyError:
113
- typer.echo(f"{values} not in expected format")
126
+ typer.echo(f"{values} globalEnv key missing")
114
127
  raise typer.Exit(1) from None
115
128
 
116
129
  with open(ioc_values) as fp:
117
130
  yaml = YAML(typ="safe").load(fp)
118
131
  try:
119
- for item in yaml["shared"]["ioc-instance"]["iocEnv"]:
132
+ for item in yaml["ioc-instance"]["iocEnv"]:
120
133
  env_vars[item["name"]] = item["value"]
121
134
  except KeyError:
122
- typer.echo(f"{ioc_values} not in expected format")
135
+ typer.echo(f"{ioc_values} iocEnv key missing")
123
136
  raise typer.Exit(1) from None
124
137
 
125
138
  this_dir = Path(__file__).parent
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.5.2'
16
- __version_tuple__ = version_tuple = (0, 5, 2)
15
+ __version__ = version = '0.6.1'
16
+ __version_tuple__ = version_tuple = (0, 6, 1)
@@ -0,0 +1,61 @@
1
+ """
2
+ functions for moving IOC assets into position for a remote IOC to access
3
+ """
4
+
5
+ import re
6
+ import shutil
7
+ from pathlib import Path
8
+
9
+ from .globals import GLOBALS
10
+
11
+
12
+ def copy_rtems():
13
+ """
14
+ Copy RTEMS binaries to a location where the RTEMS IOC can access them
15
+
16
+ IMPORTANT: local_root and nfs_root are different perspectives on the same
17
+ folder.
18
+ local_root: where the IOC files will be placed from the
19
+ perspective of this IOC proxy service. This IOC proxy will
20
+ populate the folder for use by the RTEMS crate.
21
+ nfs_root: where the IOC files will be found from the perspective of a
22
+ a client to the nfsv2-tftp service. i.e. where the RTEMS crate
23
+ will look for them using NFS.
24
+ """
25
+ local_root = GLOBALS.RTEMS_TFTP_PATH
26
+ nfs_root = Path("/iocs") / GLOBALS.IOC_NAME
27
+
28
+ # where to copy the Generic IOC folder to. This will contain the IOC binary
29
+ # and the files
30
+ dest_ioc = local_root / "ioc"
31
+ # where to copy the generated runtime assets to. This will contain
32
+ # st.cmd and ioc.db
33
+ dest_runtime = local_root / "runtime"
34
+
35
+ # TODO - perhaps do protocol files in this fashion for linux IOCs too,
36
+ # in which case this needs to go somewhere generic
37
+ protocol_folder = GLOBALS.RUNTIME / "protocol"
38
+ protocol_folder.mkdir(parents=True, exist_ok=True)
39
+ protocol_files = GLOBALS.SUPPORT.glob("**/*.proto*")
40
+ for proto_file in protocol_files:
41
+ dest = protocol_folder / proto_file.name
42
+ shutil.copy(proto_file, dest)
43
+
44
+ # copy all the files needed for runtime into the PVC that is being shared
45
+ # over nfs/tftp by the nfsv2-tftp service
46
+ for folder in ["bin", "dbd"]:
47
+ shutil.copytree(
48
+ GLOBALS.IOC.readlink() / folder, dest_ioc / folder, dirs_exist_ok=True
49
+ )
50
+ shutil.copytree(GLOBALS.RUNTIME, dest_runtime, dirs_exist_ok=True)
51
+
52
+ # because we moved the ioc files we need to fix up startup script paths
53
+ startup = dest_runtime / "st.cmd"
54
+ cmd_txt = startup.read_text()
55
+ cmd_txt = re.sub("/epics/", f"{str(nfs_root)}/", cmd_txt)
56
+ # also fix up the protocol path to point to protocol_folder
57
+ cmd_txt = (
58
+ cmd_txt
59
+ + f'\nepicsEnvSet("STREAM_PROTOCOL_PATH", "{str(nfs_root / "runtime" / "protocol")}")\n'
60
+ )
61
+ startup.write_text(cmd_txt)
@@ -0,0 +1,53 @@
1
+ #!/bin/bash
2
+
3
+ {% for name,value in env_vars.items() -%}
4
+ export {{ name }}={{ value }}
5
+ {% endfor -%}
6
+ export IOC_GROUP={{ ioc_group }}
7
+ export IOC_NAME={{ ioc_name }}
8
+ export IOC_PATH={{ ioc_path }}
9
+
10
+ if [[ "${BASH_SOURCE[0]}" == "${0}" ]] ; then
11
+ echo "This script must be sourced"
12
+ exit 1
13
+ fi
14
+
15
+ # validate we have the essential environment variables
16
+ if [[ -z "$RTEMS_TFTP_PATH" || -z "$RTEMS_TFTP_IP" || -z "$IOC_NAME" || -z "$RTEMS_TFTP_IP" ]]; then
17
+ echo "RTEMS_TFTP_PATH,RTEMS_TFTP_IP,IOC_NAME must all be set"
18
+ return 1
19
+ fi
20
+
21
+ if [[ $RTEMS_TFTP_PATH != "/"* ]]; then
22
+ echo "RTEMS_TFTP_PATH must be an absolute path"
23
+ return 1
24
+ fi
25
+
26
+ # remove previoud rsync-background process if it exists
27
+ pkill -f rsync-background &>/dev/null
28
+
29
+ ibek dev instance $IOC_PATH
30
+ bash /epics/ioc/install.sh
31
+
32
+ mkdir -p $RTEMS_TFTP_PATH
33
+
34
+ # get previous contents
35
+ echo "getting existing contents of the IOC nfs2-tftp folder"
36
+ (
37
+ set -x
38
+ rsync -rt "rsync://$RTEMS_TFTP_IP:12002/files/$IOC_NAME/" $RTEMS_TFTP_PATH 2>/dev/null
39
+ )
40
+
41
+ echo "
42
+ #!/bin/bash
43
+
44
+ while true; do
45
+ inotifywait -e modify,create,delete,move -r $RTEMS_TFTP_PATH
46
+ rsync -rt --delete /$RTEMS_TFTP_PATH/ \
47
+ "rsync://$RTEMS_TFTP_IP:12002/files/$IOC_NAME/"
48
+ done
49
+ " > /tmp/rsync-background.sh
50
+ chmod +x /tmp/rsync-background.sh
51
+
52
+ echo "launching rsync-background.sh"
53
+ nohup /tmp/rsync-background.sh &> /tmp/rsync-background.log &
@@ -48,18 +48,12 @@ class TelnetRTEMS:
48
48
  signal.signal(signal.SIGINT, self.terminate)
49
49
  signal.signal(signal.SIGTERM, self.terminate)
50
50
 
51
- def report(self, message):
52
- """
53
- print a message that is noticeable amongst all the other output
54
- """
55
- print(f"\n>>>> {message} <<<<\n")
56
-
57
51
  def terminate(self, signum, frame):
58
52
  """
59
53
  Allow the user to terminate the connection with ctrl-c while the
60
54
  pexpect child is running (but not once interactive telnet is started)
61
55
  """
62
- self.report("Terminating")
56
+ report("Terminating")
63
57
  exit(0)
64
58
 
65
59
  def connect(self):
@@ -83,7 +77,7 @@ class TelnetRTEMS:
83
77
  # if we timeout looking for failed connection that is good
84
78
  pass
85
79
  else:
86
- print(">> Cannot connect to remote IOC, connection in use? <<")
80
+ report("Cannot connect to remote IOC, connection in use?")
87
81
  raise CannotConnect
88
82
 
89
83
  def check_prompt(self, retries=5) -> RtemsState:
@@ -108,16 +102,16 @@ class TelnetRTEMS:
108
102
  # current state unknown. wait and retry
109
103
  sleep(15)
110
104
  else:
111
- self.report("Currently in bootloader")
105
+ report("Currently in bootloader")
112
106
  return RtemsState.MOT
113
107
  else:
114
- self.report("Currently in IOC shell")
108
+ report("Currently in IOC shell")
115
109
  return RtemsState.IOC
116
110
 
117
- self.report("Retrying get current status")
111
+ report("Retrying get current status")
118
112
  retries -= 1
119
113
 
120
- self.report("Current state UNKNOWN")
114
+ report("Current state UNKNOWN")
121
115
  raise CannotConnect("Current state of remote IOC unknown")
122
116
 
123
117
  def reboot(self, into: RtemsState):
@@ -127,7 +121,7 @@ class TelnetRTEMS:
127
121
  """
128
122
  assert self._child, "must call connect before reboot"
129
123
 
130
- self.report(f"Rebooting into {into.name}")
124
+ report(f"Rebooting into {into.name}")
131
125
  current_state = self.check_prompt()
132
126
  if current_state == RtemsState.MOT:
133
127
  self._child.sendline("reset")
@@ -162,7 +156,7 @@ class TelnetRTEMS:
162
156
  self.reboot(RtemsState.IOC)
163
157
  self._child.expect(self.IOC_STARTED, timeout=50)
164
158
 
165
- self.report("press enter for IOC shell prompt")
159
+ report("press enter for IOC shell prompt")
166
160
 
167
161
  def get_boot_prompt(self):
168
162
  """
@@ -177,7 +171,7 @@ class TelnetRTEMS:
177
171
  self.reboot(RtemsState.MOT)
178
172
  self._child.expect(self.MOT_PROMPT, timeout=20)
179
173
 
180
- self.report("press enter for bootloader prompt")
174
+ report("press enter for bootloader prompt")
181
175
 
182
176
  def close(self):
183
177
  if self._child:
@@ -188,6 +182,13 @@ class TelnetRTEMS:
188
182
  self.close()
189
183
 
190
184
 
185
+ def report(message):
186
+ """
187
+ print a message that is noticeable amongst all the other output
188
+ """
189
+ print(f"\n>>>> {message} <<<<\n")
190
+
191
+
191
192
  def ioc_connect(host_and_port: str, reboot: bool = False):
192
193
  """
193
194
  Entrypoint to make a connection to an RTEMS IOC over telnet.
@@ -201,10 +202,14 @@ def ioc_connect(host_and_port: str, reboot: bool = False):
201
202
 
202
203
  try:
203
204
  telnet.connect()
204
- telnet.get_epics_prompt()
205
+ if reboot:
206
+ telnet.get_epics_prompt()
207
+ else:
208
+ report("Auto reboot disabled. Skipping reboot")
205
209
  except (CannotConnect, pexpect.exceptions.TIMEOUT):
206
- print("\n\nNot Connected. Exiting...")
210
+ report("Connection failed. Exiting")
207
211
  telnet.close()
208
212
  else:
209
213
  telnet.close()
214
+ report("Connecting to IOC console, hit enter for a prompt")
210
215
  run_command(telnet.command)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: rtems-proxy
3
- Version: 0.5.2
3
+ Version: 0.6.1
4
4
  Summary: Support for a K8S proxy container in controlling and monitoring RTEMS EPICS IOCs
5
5
  Author-email: Giles Knap <giles.knap@diamond.ac.uk>
6
6
  License: Apache License
@@ -1,53 +0,0 @@
1
- """
2
- functions for moving IOC assets into position for a remote IOC to access
3
- """
4
-
5
- import re
6
- import shutil
7
- from pathlib import Path
8
-
9
- from .globals import GLOBALS
10
-
11
-
12
- def copy_rtems():
13
- """
14
- Copy RTEMS binaries to a location where the RTEMS IOC can access them
15
- """
16
- # root of pvc mount into which we copy the IOC files for the RTEMS IOC to access
17
- root = GLOBALS.RTEMS_TFTP_PATH
18
- # root of the path that the RTEMS IOC expects to find the IOC files
19
- RTEMS_TFTP_PATH = Path("/iocs") / GLOBALS.IOC_NAME
20
- # where to copy the Generic IOC folder to (at present only holds the dbd folder)
21
- ioc_dest = root / "ioc"
22
- # where to copy the generated runtime assets to (st.cmd and ioc.db)
23
- dest_runtime = root / "runtime"
24
-
25
- # move all the files needed for runtime into the PVC that is being shared
26
- # over nfs/tftp by the nfsv2-tftp service
27
- ioc_src = GLOBALS.IOC.readlink()
28
- dbd_src = ioc_src / "dbd"
29
- dbd_dest = ioc_dest / "dbd"
30
- binary = Path("bin/RTEMS-beatnik/ioc.boot")
31
- bin_rtems_src = ioc_src / binary
32
- bin_rtems_dest = ioc_dest / binary
33
- bin_rtems_dest.parent.mkdir(parents=True, exist_ok=True)
34
-
35
- shutil.copytree(dbd_src, dbd_dest, symlinks=True, dirs_exist_ok=True)
36
- shutil.copy(bin_rtems_src, bin_rtems_dest)
37
- shutil.copytree(GLOBALS.RUNTIME, dest_runtime, dirs_exist_ok=True)
38
-
39
- protocol_folder = RTEMS_TFTP_PATH / "protocol"
40
- protocol_files = GLOBALS.SUPPORT.glob("**/*.proto*")
41
- for proto_file in protocol_files:
42
- dest = protocol_folder / proto_file.name
43
- shutil.copy(proto_file, dest)
44
-
45
- # because we moved the ioc files we need to fix up startup script paths
46
- startup = dest_runtime / "st.cmd"
47
- cmd_txt = startup.read_text()
48
- cmd_txt = re.sub("/epics/", f"{str(RTEMS_TFTP_PATH)}/", cmd_txt)
49
- # also fix up the protocol path to point to protocol_folder
50
- cmd_txt = (
51
- cmd_txt + f'\nepicsEnvSet("STREAM_PROTOCOL_PATH", "{str(protocol_folder)}")\n'
52
- )
53
- startup.write_text(cmd_txt)
@@ -1,30 +0,0 @@
1
- #!/bin/bash
2
-
3
- {% for name,value in env_vars.items() -%}
4
- export {{ name }}={{ value }}
5
- {% endfor -%}
6
- export IOC_GROUP={{ ioc_group }}
7
- export IOC_NAME={{ ioc_name }}
8
- export IOC_PATH={{ ioc_path }}
9
-
10
- pkill -f rsync-background &>/dev/null
11
-
12
- ibek dev instance $IOC_PATH
13
- bash /epics/ioc/install.sh
14
-
15
- mkdir -p $RTEMS_TFTP_PATH
16
-
17
- # get previous contents
18
- rsync -rt "rsync://$RTEMS_TFTP_IP:12002/files/$IOC_GROUP/$IOC_NAME/" $RTEMS_TFTP_PATH 2>/dev/null
19
-
20
- echo "
21
- #!/bin/bash
22
-
23
- while true; do
24
- inotifywait -e modify,create,delete,move -r $RTEMS_TFTP_PATH
25
- rsync -rt --delete /$RTEMS_TFTP_PATH/ \
26
- "rsync://$RTEMS_TFTP_IP:12002/files/$IOC_GROUP/$IOC_NAME/" &> /tmp/rsync.log
27
- done
28
- " > /tmp/rsync-background.sh
29
-
30
- nohup bash /tmp/rsync-background.sh &> /tmp/rsync-background.log &
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes