Repository navigation
Open
Labels
bugbroken, incorrect, or confusing behaviorbroken, incorrect, or confusing behaviorneeds-triageseverity-low4th level, cosemtic problems, work around exists4th level, cosemtic problems, work around exists
Description
Description
According to the document, prereq only executes test=True and does not actually apply the configuration.
But I found that when prereq is used for file.line, the configuration will really be applied.
This will lead to two problems:
- The file had already been modified during the backup. Backup failed
- When we execute file.line to modify the problem, satl will prompt "no changes need to xxx".
Setup
pillar contents:
pam:
security_limits:
conf_path: /etc/security/limits.conf
add_lines:
- content: '@student - maxlogins 4'
after: '#@student - maxlogins 4'
conf_cmd:
- lss -hl
state file:
{% set backup_dir = '/root/' %}
{% for pam_item, pam_data in pillar.get('pam', {}).items() %}
{% set full_path = pam_data.get('conf_path', '') %}
{% set safe_path = full_path | replace('/', '_') | replace('.', '_') %}
{% set backup_file = 'pam_' ~ pam_item ~ '_' ~ safe_path ~ '.backup' %}
{% set backup_path = backup_dir + backup_file %}
debug_file_content_before_backup:
cmd.run:
- name: echo "===BEFORE backup===" && cat {{ full_path }} | grep -C1 "#@student"
# backup file
backup_content_{{ pam_item }}:
cmd.run:
- name: |
cp -aL {{ full_path }} {{ backup_path }}
echo "备份创建于$(date +'%Y-%m-%d %H:%M:%S.%N')"
echo "===WHEN backup===" && cat {{ full_path }} | grep -C1 "#@student"
- prereq:
{% for line in pam_data.get('add_lines', []) %}
- file: pam_{{ pam_item }}_add_line_{{ loop.index }}
{% endfor %}
debug_file_content_before:
cmd.run:
- name: echo "===BEFORE CHANGES===" && cat {{ full_path }} | grep -C1 "#@student"
# add line
{% for line in pam_data.get('add_lines', []) %}
{% set line_state = 'pam_' + pam_item + '_add_line_' + loop.index|string %}
{{ line_state }}:
file.line:
- name: {{ full_path }}
- content: "{{ line['content'] }}"
- mode: ensure
#- backup: '.bak'
- match: "{{ line.get('match', line['content']) }}"
{% if line.get('before') %}
- before: "{{ line['before'] }}"
{% endif %}
{% if line.get('after') %}
- after: "{{ line['after'] }}"
{% endif %}
{% endfor %}
# remove line...
{% endfor %}
Steps to Reproduce the behavior
execute salt-call --local state.apply , output as fellow:
local:
----------
ID: debug_file_content_before_backup
Function: cmd.run
Name: echo "===BEFORE backup===" && cat /etc/security/limits.conf | grep -C1 "#@student"
Result: True
Comment: Command "echo "===BEFORE backup===" && cat /etc/security/limits.conf | grep -C1 "#@student"" run
Started: 09:16:17.821768
Duration: 3.737 ms
Changes:
----------
pid:
116855
retcode:
0
stderr:
stdout:
===BEFORE backup===
--
#ftp hard nproc 0
#@student - maxlogins 4
----------
ID: backup_content_security_limits
Function: cmd.run
Name: cp -aL /etc/security/limits.conf /root/pam_security_limits__etc_security_limits_conf.backup
echo "备份创建于$(date +'%Y-%m-%d %H:%M:%S.%N')"
echo "===WHEN backup===" && cat /etc/security/limits.conf | grep -C1 "#@student"
Result: True
Comment: Command "cp -aL /etc/security/limits.conf /root/pam_security_limits__etc_security_limits_conf.backup
echo "备份创建于$(date +'%Y-%m-%d %H:%M:%S.%N')"
echo "===WHEN backup===" && cat /etc/security/limits.conf | grep -C1 "#@student"
" run
Started: 09:16:17.833017
Duration: 6.487 ms
Changes:
----------
pid:
116858
retcode:
0
stderr:
stdout:
备份创建于2025-04-10 09:16:17.836633182
===WHEN backup===
--
#ftp hard nproc 0
#@student - maxlogins 4
@student - maxlogins 4
----------
ID: debug_file_content_before
Function: cmd.run
Name: echo "===BEFORE CHANGES===" && cat /etc/security/limits.conf | grep -C1 "#@student"
Result: True
Comment: Command "echo "===BEFORE CHANGES===" && cat /etc/security/limits.conf | grep -C1 "#@student"" run
Started: 09:16:17.839617
Duration: 2.635 ms
Changes:
----------
pid:
116863
retcode:
0
stderr:
stdout:
===BEFORE CHANGES===
--
#ftp hard nproc 0
#@student - maxlogins 4
@student - maxlogins 4
Name: /etc/security/limits.conf - Function: file.line - Result: Clean - Started: 09:16:17.842445 - Duration: 0.968 ms
Summary for local
------------
Succeeded: 4 (changed=3)
Failed: 0
------------
Total states run: 4
Total run time: 13.827 ms
Expected behavior
before backup, output:
===BEFORE backup===
--
#ftp hard nproc 0
#@student - maxlogins 4
when backup, output:
===WHEN backup===
--
#ftp hard nproc 0
#@student - maxlogins 4
Screenshots
If applicable, add screenshots to help explain your problem.
Versions Report
salt --versions-report
(Provided by running salt --versions-report. Please also mention any differences in master/minion versions.)# salt-call --version
salt-call 3006.8 (Sulfur)Additional context
Add any other context about the problem here.
Reacted by bdrx312
Metadata
Metadata
Assignees
Labels
bugbroken, incorrect, or confusing behaviorbroken, incorrect, or confusing behaviorneeds-triageseverity-low4th level, cosemtic problems, work around exists4th level, cosemtic problems, work around exists

Activity
welcome commentedon Apr 25, 2025
Hi there! Welcome to the Salt Community! Thank you for making your first contribution. We have a lengthy process for issues and PRs. Someone from the Core Team will follow up as soon as possible. In the meantime, here’s some information that may help as you continue your Salt journey.
Please be sure to review our Code of Conduct. Also, check out some of our community resources including:
There are lots of ways to get involved in our community. Every month, there are around a dozen opportunities to meet with other contributors and the Salt Core team and collaborate in real time. The best way to keep track is by subscribing to the Salt Community Events Calendar.
If you have additional questions, email us at saltproject.pdl@broadcom.com. We’re glad you’ve joined our community and look forward to doing awesome things with you!
bdrx312 commentedon Sep 8, 2025
According to what document? prereq first executes a state with test=True to determine if it needs to run, but then runs a state if it is determined that the target state need to run. https://docs.saltproject.io/en/latest/ref/states/requisites.html#prereq
Your block below says to first run each
pam_{{ pam_item }}_add_line_{{ loop.index }}file.line state withtest=True, if it needs to run then run thecmd.runstate, and then finally actually run each of the file.line states without thetest=True.Perhaps you are wanting the functionality of one of the other requisites like onchanges https://docs.saltproject.io/en/latest/ref/states/requisites.html#onchanges
gordonwwang commentedon Sep 9, 2025
@bdrx312
Hello, thank you for your response. However, I think there have been some misunderstandings between us.
Let me explain:
1. further elaborate on the issues with file.line and prereq
My requirement is as follows:
Firstly, use prereq to check whether file.line has changed (with test=True, just a dryrun,it will not actually execute file.line). If there is a change, execute cmd.run(cp -aL origin_file backup_file) to copy the file, and then execute file.line; if there is no change, there is no need to execute cp.
The current problem is: When using prereq to check if file.line will change, it seems to actually execute file.line, modifies full_path, instead of test=True (this is a bug); then when executing file.line, salt outputs "no changes needed for xxx".
2. Why did I choose "prereq" instead of "onchanges"?
Because I need to back up the original file before executing file.line (if file.line modifies the original file).
And in the case of "onchanges", it seems that the file is backed up only after the "file.line" command is executed. At this point, the file being copied is the one that has been modified.
By the way:
When using prereq in file.managed, file.serialize, and file.replace, there is no such problem.
Only when using prereq with file.line does the bug occur.
bdrx312 commentedon Sep 9, 2025
I ran a simple test and reproduced the same
Comment: No changes needed to be made. I think the bug is only a reporting issue; I ran the simple test below to check if the file.line prereq actual behavior functions as expected.salt-call --local state.apply testingAre you experiencing the command not getting run before the the file.line changes the file or are you just noticing the report output is not expected?
Honor test mode of prereq in the file.line state
Add tests for file.line dry_run