@@ -67,8 +67,6 @@ ssm_load_project_config() {
6767 config_root=" $( ssm_config_root " ${project_dir} " ) "
6868
6969 ssm_load_key_value_file " ${config_root} /project.conf"
70- ssm_load_key_value_file " ${config_root} /project.env"
71- ssm_load_key_value_file " ${config_root} /project.env.local"
7270
7371 SSM_PROJECT_NAME=" ${PROJECT_NAME:- } "
7472 UNIT_PREFIX=" ${UNIT_PREFIX:- ${PROJECT_NAME:- project} } "
@@ -96,3 +94,139 @@ ssm_load_timer_env() {
9694 ssm_load_key_value_file " ${config_root} /timers/${timer_name} .env"
9795 ssm_load_key_value_file " ${config_root} /timers/${timer_name} .env.local"
9896}
97+
98+ # 从指定 key=value 文件中读取某个 key 的最后一个值,用于解析与环境变量同名的配置键。
99+ ssm_read_key_value_from_file () {
100+ local file_path=" $1 "
101+ local target_key=" $2 "
102+ [[ -f " ${file_path} " ]] || return 0
103+
104+ local line=" "
105+ local key=" "
106+ local value=" "
107+ local found=" "
108+
109+ while IFS= read -r line || [[ -n " ${line} " ]]; do
110+ line=" $( ssm_trim " ${line} " ) "
111+ [[ -z " ${line} " || " ${line} " == \# * ]] && continue
112+ [[ " ${line} " == * = * ]] || continue
113+
114+ key=" $( ssm_trim " ${line%% =* } " ) "
115+ value=" $( ssm_normalize_value " ${line#* =} " ) "
116+ if [[ " ${key} " == " ${target_key} " ]]; then
117+ found=" ${value} "
118+ fi
119+ done < " ${file_path} "
120+
121+ printf ' %s' " ${found} "
122+ }
123+
124+ # 清空当前待渲染的环境变量集合。
125+ ssm_reset_env_entries () {
126+ SSM_ENV_KEYS=()
127+ SSM_ENV_VALUES=()
128+ }
129+
130+ # 合并同名环境变量,后出现的值覆盖先前的值。
131+ ssm_upsert_env_entry () {
132+ local key=" $1 "
133+ local value=" $2 "
134+ local index=0
135+
136+ while [[ " ${index} " -lt " ${# SSM_ENV_KEYS[@]} " ]]; do
137+ if [[ " ${SSM_ENV_KEYS[${index}]} " == " ${key} " ]]; then
138+ SSM_ENV_VALUES[${index} ]=" ${value} "
139+ return 0
140+ fi
141+ index=$(( index + 1 ))
142+ done
143+
144+ SSM_ENV_KEYS+=(" ${key} " )
145+ SSM_ENV_VALUES+=(" ${value} " )
146+ }
147+
148+ # 把 key=value 文件合并到待渲染的环境变量集合里。
149+ ssm_merge_env_file_into_entries () {
150+ local file_path=" $1 "
151+ [[ -f " ${file_path} " ]] || return 0
152+
153+ local line=" "
154+ local key=" "
155+ local value=" "
156+
157+ while IFS= read -r line || [[ -n " ${line} " ]]; do
158+ line=" $( ssm_trim " ${line} " ) "
159+ [[ -z " ${line} " || " ${line} " == \# * ]] && continue
160+ [[ " ${line} " == * = * ]] || ssm_die " Invalid key-value line in ${file_path} : ${line} "
161+
162+ key=" $( ssm_trim " ${line%% =* } " ) "
163+ value=" $( ssm_normalize_value " ${line#* =} " ) "
164+
165+ if [[ ! " ${key} " =~ ^[A-Za-z_][A-Za-z0-9_]* $ ]]; then
166+ ssm_die " Invalid config key in ${file_path} : ${key} "
167+ fi
168+
169+ ssm_upsert_env_entry " ${key} " " ${value} "
170+ done < " ${file_path} "
171+ }
172+
173+ # 按项目级 -> 项目 local -> service 级 -> service local 顺序收集 service 环境变量。
174+ ssm_collect_env_entries_for_service () {
175+ local project_dir=" $1 "
176+ local service_name=" $2 "
177+ local config_root
178+ config_root=" $( ssm_config_root " ${project_dir} " ) "
179+
180+ ssm_reset_env_entries
181+ ssm_merge_env_file_into_entries " ${config_root} /project.env"
182+ ssm_merge_env_file_into_entries " ${config_root} /project.env.local"
183+ ssm_merge_env_file_into_entries " ${config_root} /services/${service_name} .env"
184+ ssm_merge_env_file_into_entries " ${config_root} /services/${service_name} .env.local"
185+ }
186+
187+ # 按项目级 -> 项目 local -> timer 级 -> timer local 顺序收集 timer 环境变量。
188+ ssm_collect_env_entries_for_timer () {
189+ local project_dir=" $1 "
190+ local timer_name=" $2 "
191+ local config_root
192+ config_root=" $( ssm_config_root " ${project_dir} " ) "
193+
194+ ssm_reset_env_entries
195+ ssm_merge_env_file_into_entries " ${config_root} /project.env"
196+ ssm_merge_env_file_into_entries " ${config_root} /project.env.local"
197+ ssm_merge_env_file_into_entries " ${config_root} /timers/${timer_name} .env"
198+ ssm_merge_env_file_into_entries " ${config_root} /timers/${timer_name} .env.local"
199+ }
200+
201+ # 从当前已收集的环境变量集合里读取某个 key 的值,便于调试输出。
202+ ssm_get_env_entry_value () {
203+ local target_key=" $1 "
204+ local index=0
205+
206+ while [[ " ${index} " -lt " ${# SSM_ENV_KEYS[@]} " ]]; do
207+ if [[ " ${SSM_ENV_KEYS[${index}]} " == " ${target_key} " ]]; then
208+ printf ' %s' " ${SSM_ENV_VALUES[${index}]} "
209+ return 0
210+ fi
211+ index=$(( index + 1 ))
212+ done
213+ }
214+
215+ # 对 Environment= 值做最小转义,避免双引号和反斜杠破坏 unit 语法。
216+ ssm_escape_unit_env_value () {
217+ local value=" $1 "
218+ value=" ${value// \\ / \\\\ } "
219+ value=" ${value// \" / \\\" } "
220+ printf ' %s' " ${value} "
221+ }
222+
223+ # 把当前环境变量集合渲染成 systemd Environment= 行。
224+ ssm_render_environment_lines () {
225+ local index=0
226+ while [[ " ${index} " -lt " ${# SSM_ENV_KEYS[@]} " ]]; do
227+ printf ' Environment="%s=%s"\n' \
228+ " ${SSM_ENV_KEYS[${index}]} " \
229+ " $( ssm_escape_unit_env_value " ${SSM_ENV_VALUES[${index}]} " ) "
230+ index=$(( index + 1 ))
231+ done
232+ }
0 commit comments