1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 import os
38
41 '''
42 The class to handle the running screen sessions and create new sessions on
43 start of the ROS nodes.
44 '''
45
46 LOG_PATH = ''.join([os.environ.get('ROS_LOG_DIR'), os.path.sep]) if os.environ.get('ROS_LOG_DIR') else os.path.join(os.path.expanduser('~'), '.ros/log/')
47 SCREEN = "/usr/bin/screen"
48 SLASH_SEP = '_'
49
50 @classmethod
52 '''
53 Creates a name for the screen session. All slash separators are replaced by
54 L{SLASH_SEP}
55 @param node: the name of the node
56 @type node: C{str}
57 @return: name for the screen session.
58 @rtype: C{str}
59 '''
60
61
62 node_name = str(node).replace('/', cls.SLASH_SEP) if node is not None else ''
63
64 return node_name
65
66 @classmethod
68 '''
69 Splits the screen session name into PID and session name generated by
70 L{createSessionName()}.
71 @param session: the screen session name
72 @type session: C{str}
73 @return: PID, session name generated by L{createSessionName()}. Not presented
74 values are coded as empty strings. Not valid session names have an empty
75 PID string.
76 @rtype: C{str, str}
77 '''
78 result = session.split('.', 1)
79 if len(result) != 2:
80 return '', ''
81 pid = result[0]
82 node = result[1]
83
84
85 return pid, node
86
87 @classmethod
89 '''
90 Tests for whether the SCREEN binary exists and raise an exception if not.
91 @raise ScreenHandlerException: if the screen binary not found.
92 '''
93 if not os.path.isfile(cls.SCREEN):
94 raise ScreenHandlerException(''.join([cls.SCREEN, " is missing"]))
95
96 @classmethod
98 '''
99 Generates a log file name of the ROS log.
100 @param node: the name of the node
101 @type node: C{str}
102 @return: the ROS log file name
103 @rtype: C{str}
104 @todo: get the run_id from the ROS parameter server and search in this log folder
105 for the log file (handle the node started using a launch file).
106 '''
107 if session is not None:
108 return "%s%s.log" % (cls.LOG_PATH, session)
109 elif node is not None:
110 return "%s%s.log" % (cls.LOG_PATH, cls.createSessionName(node))
111 else:
112 return "%s%s.log" % (cls.LOG_PATH, 'unknown')
113
114 @classmethod
116 '''
117 Generates a log file name for the ROS log
118 @param node: the name of the node
119 @type node: C{str}
120 @return: the log file name
121 @rtype: C{str}
122 '''
123 if node is not None:
124 return "%s%s.log" % (cls.LOG_PATH, node.strip('/').replace('/', '_'))
125 else:
126 return ''
127
128 @classmethod
130 '''
131 Generates a configuration file name for the screen session.
132 @param session: the name of the screen session
133 @type session: C{str}
134 @return: the configuration file name
135 @rtype: C{str}
136 '''
137 if session is not None:
138 return "%s%s.conf" % (cls.LOG_PATH, session)
139 elif node is not None:
140 return "%s%s.log" % (cls.LOG_PATH, cls.createSessionName(node))
141 else:
142 return "%s%s.log" % (cls.LOG_PATH, 'unknown')
143
144 @classmethod
146 '''
147 Generates a PID file name for the screen session.
148 @param session: the name of the screen session
149 @type session: C{str}
150 @return: the PID file name
151 @rtype: C{str}
152 '''
153 if session is not None:
154 return "%s%s.pid" % (cls.LOG_PATH, session)
155 elif node is not None:
156 return "%s%s.pid" % (cls.LOG_PATH, cls.createSessionName(node))
157 else:
158 return "%s%s.pid" % (cls.LOG_PATH, 'unknown')
159
160 @classmethod
162 '''
163 Generates a configuration file and return the command prefix to start the given node
164 in a screen terminal.
165 @param node: the name of the node
166 @type node: C{str}
167 @return: the command prefix
168 @rtype: C{str}
169 '''
170 filename = cls.getScreenCfgFile(node=node)
171 f = None
172 try:
173 f = open(cls.getScreenCfgFile(node=node), 'w')
174 except Exception:
175 os.makedirs(os.path.dirname(filename))
176 f = open(cls.getScreenCfgFile(node=node), 'w')
177 f.write(''.join(["logfile ", cls.getScreenLogFile(node=node), "\n"]))
178 f.write("logfile flush 0\n")
179 f.write("defscrollback 10000\n")
180 ld_library_path = os.getenv('LD_LIBRARY_PATH', '')
181 if ld_library_path:
182 f.write(' '.join(['setenv', 'LD_LIBRARY_PATH', ld_library_path, "\n"]))
183 ros_etc_dir = os.getenv('ROS_ETC_DIR', '')
184 if ros_etc_dir:
185 f.write(' '.join(['setenv', 'ROS_ETC_DIR', ros_etc_dir, "\n"]))
186 f.close()
187 return ' '.join([cls.SCREEN, '-c', cls.getScreenCfgFile(node=node), '-L', '-dmS', cls.createSessionName(node=node)])
188